Consolidate token symbols

This commit is contained in:
Jeff 2024-06-20 19:25:46 -04:00
parent a94251e707
commit 880fb7cd1b
4 changed files with 229 additions and 242 deletions

View File

@ -12,7 +12,7 @@ use super::{Block, Evaluate, Evaluation, ExpectedType, Expression, Type, WithPos
pub struct IfElse {
if_expression: Expression,
if_block: WithPosition<Block>,
else_ifs: Vec<(Expression, WithPosition<Block>)>,
else_ifs: Option<Vec<(Expression, WithPosition<Block>)>>,
else_block: Option<WithPosition<Block>>,
}
@ -20,7 +20,7 @@ impl IfElse {
pub fn new(
if_expression: Expression,
if_block: WithPosition<Block>,
else_ifs: Vec<(Expression, WithPosition<Block>)>,
else_ifs: Option<Vec<(Expression, WithPosition<Block>)>>,
else_block: Option<WithPosition<Block>>,
) -> Self {
Self {
@ -61,26 +61,28 @@ impl Evaluate for IfElse {
});
}
for (expression, block) in &self.else_ifs {
let expression_type = expression.expected_type(context)?;
if let Some(else_ifs) = &self.else_ifs {
for (expression, block) in else_ifs {
let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type {
block.node.validate(context, manage_memory)?;
if let Type::Boolean = expression_type {
block.node.validate(context, manage_memory)?;
let actual = block.node.expected_type(context)?;
let actual = block.node.expected_type(context)?;
expected_type
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.node.last_statement().position(),
expected_position: Some(self.if_expression.position()),
expected_type.check(&actual).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.node.last_statement().position(),
expected_position: Some(self.if_expression.position()),
}
})?;
} else {
return Err(ValidationError::ExpectedBoolean {
actual: if_expression_type,
position: self.if_expression.position(),
});
} else {
return Err(ValidationError::ExpectedBoolean {
actual: if_expression_type,
position: self.if_expression.position(),
});
}
}
}
@ -104,9 +106,11 @@ impl Evaluate for IfElse {
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean {
self.if_block.node.evaluate(context, _manage_memory)
} else {
for (expression, block) in self.else_ifs {
return self.if_block.node.evaluate(context, _manage_memory);
}
if let Some(else_ifs) = self.else_ifs {
for (expression, block) in else_ifs {
let expression_position = expression.position();
let action = expression.evaluate(context, _manage_memory)?;
let value = if let Evaluation::Return(value) = action {
@ -130,12 +134,12 @@ impl Evaluate for IfElse {
));
}
}
}
if let Some(else_statement) = self.else_block {
else_statement.node.evaluate(context, _manage_memory)
} else {
Ok(Evaluation::None)
}
if let Some(else_statement) = self.else_block {
else_statement.node.evaluate(context, _manage_memory)
} else {
Ok(Evaluation::None)
}
} else {
Err(RuntimeError::ValidationFailure(
@ -172,7 +176,7 @@ mod tests {
ValueNode::String("foo".to_string()).with_position((0, 0))
))])
.with_position((0, 0)),
Vec::with_capacity(0),
Some(Vec::with_capacity(0)),
None
)
.evaluate(&mut Context::new(None), true)

View File

@ -15,8 +15,7 @@ pub enum Token<'src> {
Float(f64),
String(&'src str),
Identifier(&'src str),
Operator(Operator),
Control(Control),
Symbol(Symbol),
Keyword(Keyword),
}
@ -29,8 +28,7 @@ impl<'src> Display for Token<'src> {
Token::Float(float) => write!(f, "{float}"),
Token::String(string) => write!(f, "{string}"),
Token::Identifier(string) => write!(f, "{string}"),
Token::Operator(operator) => write!(f, "{operator}"),
Token::Control(control) => write!(f, "{control}"),
Token::Symbol(control) => write!(f, "{control}"),
Token::Keyword(keyword) => write!(f, "{keyword}"),
}
}
@ -100,91 +98,80 @@ impl Display for Keyword {
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Operator {
Add,
AddAssign,
And,
Assign,
Divide,
pub enum Symbol {
Plus,
PlusEquals,
DoubleAmpersand,
Colon,
Comma,
CurlyClose,
CurlyOpen,
Slash,
Dollar,
Dot,
DoubleColon,
DoubleDot,
DoubleEqual,
DoubleUnderscore,
Equal,
FatArrow,
Greater,
GreaterOrEqual,
Less,
LessOrEqual,
Modulo,
Multiply,
Not,
Percent,
Asterisk,
Exclamation,
NotEqual,
Or,
SubAssign,
Subtract,
}
impl Display for Operator {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Operator::Add => write!(f, "+"),
Operator::AddAssign => write!(f, "+="),
Operator::And => write!(f, "&&"),
Operator::Assign => write!(f, "="),
Operator::Divide => write!(f, "="),
Operator::Equal => write!(f, "=="),
Operator::Greater => write!(f, ">"),
Operator::GreaterOrEqual => write!(f, ">="),
Operator::Less => write!(f, "<"),
Operator::LessOrEqual => write!(f, "<="),
Operator::Modulo => write!(f, "%"),
Operator::Multiply => write!(f, "*"),
Operator::Not => write!(f, "!"),
Operator::NotEqual => write!(f, "!="),
Operator::Or => write!(f, "||"),
Operator::SubAssign => write!(f, "-="),
Operator::Subtract => write!(f, "-"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Control {
CurlyOpen,
CurlyClose,
SquareOpen,
SquareClose,
ParenOpen,
DoublePipe,
ParenClose,
ParenOpen,
Pipe,
Comma,
DoubleColon,
Colon,
Dollar,
Dot,
DoubleDot,
Semicolon,
SkinnyArrow,
FatArrow,
DoubleUnderscore,
SquareClose,
SquareOpen,
MinusEqual,
Minus,
}
impl Display for Control {
impl Display for Symbol {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Control::CurlyOpen => write!(f, "{{"),
Control::CurlyClose => write!(f, "}}"),
Control::Dollar => write!(f, "$"),
Control::SquareOpen => write!(f, "["),
Control::SquareClose => write!(f, "]"),
Control::ParenOpen => write!(f, "("),
Control::ParenClose => write!(f, ")"),
Control::Pipe => write!(f, "|"),
Control::Comma => write!(f, ","),
Control::DoubleColon => write!(f, "::"),
Control::Colon => write!(f, ":"),
Control::Dot => write!(f, "."),
Control::Semicolon => write!(f, ";"),
Control::DoubleDot => write!(f, ".."),
Control::SkinnyArrow => write!(f, "->"),
Control::FatArrow => write!(f, "=>"),
Control::DoubleUnderscore => write!(f, "__"),
Symbol::Asterisk => write!(f, "*"),
Symbol::Colon => write!(f, ":"),
Symbol::Comma => write!(f, ","),
Symbol::CurlyClose => write!(f, "}}"),
Symbol::CurlyOpen => write!(f, "{{"),
Symbol::Dollar => write!(f, "$"),
Symbol::Dot => write!(f, "."),
Symbol::DoubleAmpersand => write!(f, "&&"),
Symbol::DoubleColon => write!(f, "::"),
Symbol::DoubleDot => write!(f, ".."),
Symbol::DoubleEqual => write!(f, "=="),
Symbol::DoublePipe => write!(f, "||"),
Symbol::DoubleUnderscore => write!(f, "__"),
Symbol::Equal => write!(f, "="),
Symbol::Exclamation => write!(f, "!"),
Symbol::FatArrow => write!(f, "=>"),
Symbol::Greater => write!(f, ">"),
Symbol::GreaterOrEqual => write!(f, ">="),
Symbol::Less => write!(f, "<"),
Symbol::LessOrEqual => write!(f, "<="),
Symbol::Minus => write!(f, "-"),
Symbol::MinusEqual => write!(f, "-="),
Symbol::NotEqual => write!(f, "!="),
Symbol::ParenClose => write!(f, ")"),
Symbol::ParenOpen => write!(f, "("),
Symbol::Percent => write!(f, "%"),
Symbol::Pipe => write!(f, "|"),
Symbol::Plus => write!(f, "+"),
Symbol::PlusEquals => write!(f, "+="),
Symbol::Semicolon => write!(f, ";"),
Symbol::SkinnyArrow => write!(f, "->"),
Symbol::Slash => write!(f, "/"),
Symbol::SquareClose => write!(f, "]"),
Symbol::SquareOpen => write!(f, "["),
}
}
}
@ -294,51 +281,42 @@ pub fn lexer<'src>() -> impl Parser<
_ => Token::Identifier(text),
});
let operator = choice((
// logic
just("&&").to(Operator::And),
just("==").to(Operator::Equal),
just("!=").to(Operator::NotEqual),
just(">=").to(Operator::GreaterOrEqual),
just("<=").to(Operator::LessOrEqual),
just(">").to(Operator::Greater),
just("<").to(Operator::Less),
just("!").to(Operator::Not),
just("!=").to(Operator::NotEqual),
just("||").to(Operator::Or),
// assignment
just("=").to(Operator::Assign),
just("+=").to(Operator::AddAssign),
just("-=").to(Operator::SubAssign),
// math
just("+").to(Operator::Add),
just("-").to(Operator::Subtract),
just("*").to(Operator::Multiply),
just("/").to(Operator::Divide),
just("%").to(Operator::Modulo),
))
.map(Token::Operator);
let control = choice((
just("->").to(Control::SkinnyArrow),
just("=>").to(Control::FatArrow),
just("{").to(Control::CurlyOpen),
just("}").to(Control::CurlyClose),
just("[").to(Control::SquareOpen),
just("]").to(Control::SquareClose),
just("(").to(Control::ParenOpen),
just(")").to(Control::ParenClose),
just("|").to(Control::Pipe),
just(",").to(Control::Comma),
just(";").to(Control::Semicolon),
just("::").to(Control::DoubleColon),
just(":").to(Control::Colon),
just("..").to(Control::DoubleDot),
just(".").to(Control::Dot),
just("$").to(Control::Dollar),
just("__").to(Control::DoubleUnderscore),
))
.map(Token::Control);
let symbol = choice([
just("!=").to(Token::Symbol(Symbol::NotEqual)),
just("!").to(Token::Symbol(Symbol::Exclamation)),
just("$").to(Token::Symbol(Symbol::Dollar)),
just("%").to(Token::Symbol(Symbol::Percent)),
just("&&").to(Token::Symbol(Symbol::DoubleAmpersand)),
just("(").to(Token::Symbol(Symbol::ParenOpen)),
just(")").to(Token::Symbol(Symbol::ParenClose)),
just("*").to(Token::Symbol(Symbol::Asterisk)),
just("+=").to(Token::Symbol(Symbol::PlusEquals)),
just("+").to(Token::Symbol(Symbol::Plus)),
just(",").to(Token::Symbol(Symbol::Comma)),
just("->").to(Token::Symbol(Symbol::SkinnyArrow)),
just("-=").to(Token::Symbol(Symbol::MinusEqual)),
just("-").to(Token::Symbol(Symbol::Minus)),
just("..").to(Token::Symbol(Symbol::DoubleDot)),
just(".").to(Token::Symbol(Symbol::Dot)),
just("/").to(Token::Symbol(Symbol::Slash)),
just("::").to(Token::Symbol(Symbol::DoubleColon)),
just(":").to(Token::Symbol(Symbol::Colon)),
just(";").to(Token::Symbol(Symbol::Semicolon)),
just("<=").to(Token::Symbol(Symbol::LessOrEqual)),
just("<").to(Token::Symbol(Symbol::Less)),
just("=>").to(Token::Symbol(Symbol::FatArrow)),
just("==").to(Token::Symbol(Symbol::DoubleEqual)),
just("=").to(Token::Symbol(Symbol::Equal)),
just(">=").to(Token::Symbol(Symbol::GreaterOrEqual)),
just(">").to(Token::Symbol(Symbol::Greater)),
just("[").to(Token::Symbol(Symbol::SquareOpen)),
just("]").to(Token::Symbol(Symbol::SquareClose)),
just("__").to(Token::Symbol(Symbol::DoubleUnderscore)),
just("{").to(Token::Symbol(Symbol::CurlyOpen)),
just("||").to(Token::Symbol(Symbol::DoublePipe)),
just("|").to(Token::Symbol(Symbol::Pipe)),
just("}").to(Token::Symbol(Symbol::CurlyClose)),
]);
choice((
line_comment,
@ -348,10 +326,9 @@ pub fn lexer<'src>() -> impl Parser<
integer,
string,
identifier_and_keyword,
control,
operator,
symbol,
))
.map_with(|token, state| (token, state.span()))
.map_with(|token: Token, state| (token, state.span()))
.padded()
.repeated()
.collect()
@ -427,7 +404,7 @@ mod tests {
lex("1..10").unwrap(),
vec![
(Token::Integer(1), (0..1).into()),
(Token::Control(Control::DoubleDot), (1..3).into()),
(Token::Symbol(Symbol::DoubleDot), (1..3).into()),
(Token::Integer(10), (3..5).into())
]
)
@ -439,7 +416,7 @@ mod tests {
lex("1 + 1").unwrap(),
vec![
(Token::Integer(1), (0..1).into()),
(Token::Operator(Operator::Add), (2..3).into()),
(Token::Symbol(Symbol::Plus), (2..3).into()),
(Token::Integer(1), (4..5).into())
]
)

View File

@ -9,7 +9,7 @@ use crate::{
abstract_tree::*,
error::DustError,
identifier::Identifier,
lexer::{Control, Keyword, Operator, Token},
lexer::{Keyword, Symbol, Token},
};
use self::{
@ -96,26 +96,26 @@ pub fn parser<'src>(
.ignore_then(
positioned_identifier
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1)
.collect()
.delimited_by(
just(Token::Control(Control::Pipe)),
just(Token::Control(Control::Pipe)),
just(Token::Symbol(Symbol::Pipe)),
just(Token::Symbol(Symbol::Pipe)),
)
.or_not(),
)
.then(
type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
),
)
.then_ignore(just(Token::Control(Control::SkinnyArrow)))
.then_ignore(just(Token::Symbol(Symbol::SkinnyArrow)))
.then(type_constructor.clone())
.map_with(
|((type_parameters, value_parameters), return_type), state| {
@ -132,11 +132,11 @@ pub fn parser<'src>(
let list_type = type_constructor
.clone()
.then_ignore(just(Token::Control(Control::Semicolon)))
.then_ignore(just(Token::Symbol(Symbol::Semicolon)))
.then(raw_integer.clone())
.delimited_by(
just(Token::Control(Control::SquareOpen)),
just(Token::Control(Control::SquareClose)),
just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Symbol(Symbol::SquareClose)),
)
.map_with(|(item_type, length), state| {
TypeConstructor::List(
@ -151,8 +151,8 @@ pub fn parser<'src>(
let list_of_type = type_constructor
.clone()
.delimited_by(
just(Token::Control(Control::SquareOpen)),
just(Token::Control(Control::SquareClose)),
just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Symbol(Symbol::SquareClose)),
)
.map_with(|item_type, state| {
TypeConstructor::ListOf(Box::new(item_type).with_position(state.span()))
@ -163,13 +163,13 @@ pub fn parser<'src>(
.then(
type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1)
.allow_trailing()
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
)
.or_not(),
)
@ -190,7 +190,7 @@ pub fn parser<'src>(
});
let type_specification =
just(Token::Control(Control::Colon)).ignore_then(type_constructor.clone());
just(Token::Symbol(Symbol::Colon)).ignore_then(type_constructor.clone());
let statement = recursive(|statement| {
let allow_built_ins = allow_built_ins.clone();
@ -201,8 +201,8 @@ pub fn parser<'src>(
.at_least(1)
.collect()
.delimited_by(
just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)),
just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Symbol(Symbol::CurlyClose)),
)
.map_with(|statements, state| Block::new(statements).with_position(state.span()));
@ -215,7 +215,7 @@ pub fn parser<'src>(
let range = raw_integer
.clone()
.then_ignore(just(Token::Control(Control::DoubleDot)))
.then_ignore(just(Token::Symbol(Symbol::DoubleDot)))
.then(raw_integer)
.map_with(|(start, end), state| {
Expression::Value(ValueNode::Range(start..end).with_position(state.span()))
@ -223,12 +223,12 @@ pub fn parser<'src>(
let list = expression
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing()
.collect()
.delimited_by(
just(Token::Control(Control::SquareOpen)),
just(Token::Control(Control::SquareClose)),
just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Symbol(Symbol::SquareClose)),
)
.map_with(|list, state| {
Expression::Value(ValueNode::List(list).with_position(state.span()))
@ -237,17 +237,17 @@ pub fn parser<'src>(
let map_fields = identifier
.clone()
.then(type_specification.clone().or_not())
.then_ignore(just(Token::Operator(Operator::Assign)))
.then_ignore(just(Token::Symbol(Symbol::Equal)))
.then(expression.clone())
.map(|((identifier, r#type), expression)| (identifier, r#type, expression));
let map = map_fields
.separated_by(just(Token::Control(Control::Comma)).or_not())
.separated_by(just(Token::Symbol(Symbol::Comma)).or_not())
.allow_trailing()
.collect()
.delimited_by(
just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)),
just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Symbol(Symbol::CurlyClose)),
)
.map_with(|map_assigment_list, state| {
Expression::Value(
@ -259,30 +259,30 @@ pub fn parser<'src>(
.ignore_then(
identifier
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1)
.allow_trailing()
.collect()
.delimited_by(
just(Token::Control(Control::Pipe)),
just(Token::Control(Control::Pipe)),
just(Token::Symbol(Symbol::Pipe)),
just(Token::Symbol(Symbol::Pipe)),
)
.or_not(),
)
.then(
identifier
.clone()
.then_ignore(just(Token::Control(Control::Colon)))
.then_ignore(just(Token::Symbol(Symbol::Colon)))
.then(type_constructor.clone())
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing()
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
),
)
.then_ignore(just(Token::Control(Control::SkinnyArrow)))
.then_ignore(just(Token::Symbol(Symbol::SkinnyArrow)))
.then(type_constructor.clone())
.then(block.clone())
.map_with(
@ -301,16 +301,16 @@ pub fn parser<'src>(
let enum_instance = positioned_identifier
.clone()
.then_ignore(just(Token::Control(Control::DoubleColon)))
.then_ignore(just(Token::Symbol(Symbol::DoubleColon)))
.then(positioned_identifier.clone())
.then(
expression
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
)
.or_not(),
)
@ -386,16 +386,16 @@ pub fn parser<'src>(
let turbofish = type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1)
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
)
.delimited_by(
just(Token::Control(Control::DoubleColon)),
just(Token::Control(Control::DoubleColon)),
just(Token::Symbol(Symbol::DoubleColon)),
just(Token::Symbol(Symbol::DoubleColon)),
);
let atom = choice((
@ -407,8 +407,8 @@ pub fn parser<'src>(
basic_value.clone(),
identifier_expression.clone(),
expression.clone().delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
),
));
@ -416,21 +416,21 @@ pub fn parser<'src>(
// Logic
prefix(
2,
just(Token::Operator(Operator::Not)),
just(Token::Symbol(Symbol::Exclamation)),
|_, expression, span| {
Expression::Logic(Box::new(Logic::Not(expression)).with_position(span))
},
),
infix(
left(1),
just(Token::Operator(Operator::Equal)),
just(Token::Symbol(Symbol::DoubleEqual)),
|left, _, right, span| {
Expression::Logic(Box::new(Logic::Equal(left, right)).with_position(span))
},
),
infix(
left(1),
just(Token::Operator(Operator::NotEqual)),
just(Token::Symbol(Symbol::NotEqual)),
|left, _, right, span| {
Expression::Logic(
Box::new(Logic::NotEqual(left, right)).with_position(span),
@ -439,21 +439,21 @@ pub fn parser<'src>(
),
infix(
left(1),
just(Token::Operator(Operator::Greater)),
just(Token::Symbol(Symbol::Greater)),
|left, _, right, span| {
Expression::Logic(Box::new(Logic::Greater(left, right)).with_position(span))
},
),
infix(
left(1),
just(Token::Operator(Operator::Less)),
just(Token::Symbol(Symbol::Less)),
|left, _, right, span| {
Expression::Logic(Box::new(Logic::Less(left, right)).with_position(span))
},
),
infix(
left(1),
just(Token::Operator(Operator::GreaterOrEqual)),
just(Token::Symbol(Symbol::GreaterOrEqual)),
|left, _, right, span| {
Expression::Logic(
Box::new(Logic::GreaterOrEqual(left, right)).with_position(span),
@ -462,7 +462,7 @@ pub fn parser<'src>(
),
infix(
left(1),
just(Token::Operator(Operator::LessOrEqual)),
just(Token::Symbol(Symbol::LessOrEqual)),
|left, _, right, span| {
Expression::Logic(
Box::new(Logic::LessOrEqual(left, right)).with_position(span),
@ -471,14 +471,14 @@ pub fn parser<'src>(
),
infix(
left(1),
just(Token::Operator(Operator::And)),
just(Token::Symbol(Symbol::DoubleAmpersand)),
|left, _, right, span| {
Expression::Logic(Box::new(Logic::And(left, right)).with_position(span))
},
),
infix(
left(1),
just(Token::Operator(Operator::Or)),
just(Token::Symbol(Symbol::DoublePipe)),
|left, _, right, span| {
Expression::Logic(Box::new(Logic::Or(left, right)).with_position(span))
},
@ -486,35 +486,35 @@ pub fn parser<'src>(
// Math
infix(
left(1),
just(Token::Operator(Operator::Add)),
just(Token::Symbol(Symbol::Plus)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Add(left, right)).with_position(span))
},
),
infix(
left(1),
just(Token::Operator(Operator::Subtract)),
just(Token::Symbol(Symbol::Minus)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Subtract(left, right)).with_position(span))
},
),
infix(
left(2),
just(Token::Operator(Operator::Multiply)),
just(Token::Symbol(Symbol::Asterisk)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Multiply(left, right)).with_position(span))
},
),
infix(
left(2),
just(Token::Operator(Operator::Divide)),
just(Token::Symbol(Symbol::Slash)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Divide(left, right)).with_position(span))
},
),
infix(
left(1),
just(Token::Operator(Operator::Modulo)),
just(Token::Symbol(Symbol::Slash)),
|left, _, right, span| {
Expression::Math(Box::new(Math::Modulo(left, right)).with_position(span))
},
@ -522,7 +522,7 @@ pub fn parser<'src>(
// Indexes
infix(
left(4),
just(Token::Control(Control::Dot)),
just(Token::Symbol(Symbol::Dot)),
|left, _, right, span| {
Expression::MapIndex(
Box::new(MapIndex::new(left, right)).with_position(span),
@ -532,8 +532,8 @@ pub fn parser<'src>(
postfix(
3,
expression.clone().delimited_by(
just(Token::Control(Control::SquareOpen)),
just(Token::Control(Control::SquareClose)),
just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Symbol(Symbol::SquareClose)),
),
|left, right, span| {
Expression::ListIndex(
@ -547,11 +547,11 @@ pub fn parser<'src>(
turbofish.clone().or_not().then(
expression
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
),
),
|function_expression, (type_parameters, value_parameters), span| {
@ -596,8 +596,8 @@ pub fn parser<'src>(
let async_block = just(Token::Keyword(Keyword::Async))
.ignore_then(statement.clone().repeated().collect().delimited_by(
just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)),
just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Symbol(Symbol::CurlyClose)),
))
.map_with(|statements, state| {
Statement::AsyncBlock(AsyncBlock::new(statements).with_position(state.span()))
@ -610,9 +610,9 @@ pub fn parser<'src>(
.clone()
.then(type_specification.clone().or_not())
.then(choice((
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign),
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign),
just(Token::Operator(Operator::SubAssign)).to(AssignmentOperator::SubAssign),
just(Token::Symbol(Symbol::Equal)).to(AssignmentOperator::Assign),
just(Token::Symbol(Symbol::PlusEquals)).to(AssignmentOperator::AddAssign),
just(Token::Symbol(Symbol::MinusEqual)).to(AssignmentOperator::SubAssign),
)))
.then(statement.clone())
.map_with(|(((identifier, r#type), operator), statement), state| {
@ -630,8 +630,8 @@ pub fn parser<'src>(
.at_least(1)
.collect()
.delimited_by(
just(Token::Keyword(Keyword::Loop)).then(just(Token::Control(Control::CurlyOpen))),
just(Token::Control(Control::CurlyClose)),
just(Token::Keyword(Keyword::Loop)).then(just(Token::Symbol(Symbol::CurlyOpen))),
just(Token::Symbol(Symbol::CurlyClose)),
)
.map_with(|statements, state| {
Statement::Loop(Loop::new(statements).with_position(state.span()))
@ -640,8 +640,8 @@ pub fn parser<'src>(
let r#while = just(Token::Keyword(Keyword::While))
.ignore_then(expression.clone())
.then(statement.clone().repeated().collect().delimited_by(
just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)),
just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Symbol(Symbol::CurlyClose)),
))
.map_with(|(expression, statements), state| {
Statement::While(While::new(expression, statements).with_position(state.span()))
@ -656,7 +656,9 @@ pub fn parser<'src>(
.ignore_then(expression.clone())
.then(block.clone())
.repeated()
.collect(),
.at_least(1)
.collect()
.or_not(),
)
.then(
just(Token::Keyword(Keyword::Else))
@ -674,7 +676,7 @@ pub fn parser<'src>(
let type_alias = just(Token::Keyword(Keyword::Type))
.ignore_then(positioned_identifier.clone())
.then_ignore(just(Token::Operator(Operator::Assign)))
.then_ignore(just(Token::Symbol(Symbol::Equal)))
.then(type_constructor.clone())
.map_with(|(identifier, constructor), state| {
Statement::TypeAlias(
@ -687,11 +689,11 @@ pub fn parser<'src>(
.then(
type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Symbol(Symbol::ParenClose)),
)
.or_not(),
)
@ -705,24 +707,24 @@ pub fn parser<'src>(
.then(
positioned_identifier
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing()
.collect()
.delimited_by(
just(Token::Operator(Operator::Less)),
just(Token::Operator(Operator::Greater)),
just(Token::Symbol(Symbol::Less)),
just(Token::Symbol(Symbol::Greater)),
)
.or_not(),
)
.then(
enum_variant
.separated_by(just(Token::Control(Control::Comma)))
.separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing()
.at_least(1)
.collect()
.delimited_by(
just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)),
just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Symbol(Symbol::CurlyClose)),
),
)
.map_with(|((name, type_parameters), variants), state| {
@ -751,7 +753,7 @@ pub fn parser<'src>(
type_alias,
enum_declaration,
)))
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
.then_ignore(just(Token::Symbol(Symbol::Semicolon)).or_not())
});
statement.repeated().collect()

View File

@ -587,7 +587,7 @@ fn r#if() {
ValueNode::String("foo".to_string()).with_position((10, 15))
))])
.with_position((8, 17)),
Vec::with_capacity(0),
None,
None
)
.with_position((0, 17))
@ -606,7 +606,7 @@ fn if_else() {
ValueNode::String("foo".to_string()).with_position((9, 14))
))])
.with_position((8, 16)),
Vec::with_capacity(0),
None,
Some(
Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("bar".to_string()).with_position((24, 29))
@ -695,6 +695,10 @@ fn r#loop() {
.with_position((0, 11))
)
);
}
#[test]
fn complex_loop() {
assert_eq!(
parse(&lex("loop { if i > 2 { break } else { i += 1 } }").unwrap()).unwrap()[0],
Statement::Loop(
@ -709,7 +713,7 @@ fn r#loop() {
),
Block::new(vec![Statement::Break(().with_position((18, 23)))])
.with_position((16, 25)),
Vec::with_capacity(0),
None,
Some(
Block::new(vec![Statement::Assignment(
Assignment::new(