From 880fb7cd1b68238592266395dfef526e277ac68e Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 20 Jun 2024 19:25:46 -0400 Subject: [PATCH] Consolidate token symbols --- dust-lang/src/abstract_tree/if_else.rs | 58 ++++--- dust-lang/src/lexer.rs | 227 +++++++++++-------------- dust-lang/src/parser/mod.rs | 176 +++++++++---------- dust-lang/src/parser/tests.rs | 10 +- 4 files changed, 229 insertions(+), 242 deletions(-) diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index 610a02f..d20baf8 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -12,7 +12,7 @@ use super::{Block, Evaluate, Evaluation, ExpectedType, Expression, Type, WithPos pub struct IfElse { if_expression: Expression, if_block: WithPosition, - else_ifs: Vec<(Expression, WithPosition)>, + else_ifs: Option)>>, else_block: Option>, } @@ -20,7 +20,7 @@ impl IfElse { pub fn new( if_expression: Expression, if_block: WithPosition, - else_ifs: Vec<(Expression, WithPosition)>, + else_ifs: Option)>>, else_block: Option>, ) -> 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) diff --git a/dust-lang/src/lexer.rs b/dust-lang/src/lexer.rs index 1973e08..ed89551 100644 --- a/dust-lang/src/lexer.rs +++ b/dust-lang/src/lexer.rs @@ -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()) ] ) diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index ae28aa7..2827a66 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -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() diff --git a/dust-lang/src/parser/tests.rs b/dust-lang/src/parser/tests.rs index 5fd14f4..6f4bbd5 100644 --- a/dust-lang/src/parser/tests.rs +++ b/dust-lang/src/parser/tests.rs @@ -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(