From 486530610bc98562739e4c30181af2b11e579037 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 15 Aug 2024 00:20:36 -0400 Subject: [PATCH] Continue passing tests and tweaking --- dust-lang/src/abstract_tree/expression.rs | 221 +++++++++++++++--- dust-lang/src/parser.rs | 269 ++++++++++------------ dust-lang/src/token.rs | 21 +- 3 files changed, 320 insertions(+), 191 deletions(-) diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 85e4437..52882e0 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -16,27 +16,6 @@ pub enum Expression { } impl Expression { - pub fn range(range: Range, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Range(range)), - position, - )) - } - - pub fn call(call_expression: CallExpression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Call(call_expression)), - position, - )) - } - - pub fn field_access(field_access: FieldAccess, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::FieldAccess(field_access)), - position, - )) - } - pub fn operator(operator_expression: OperatorExpression, position: Span) -> Self { Expression::WithoutBlock(Node::new( Box::new(ExpressionWithoutBlock::Operator(operator_expression)), @@ -44,9 +23,175 @@ impl Expression { )) } - pub fn r#loop(r#loop: Loop, position: Span) -> Self { + pub fn range(start: Expression, end: Expression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Range(Range { start, end })), + position, + )) + } + + pub fn call(invoker: Expression, arguments: Vec, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Call(CallExpression { + invoker, + arguments, + })), + position, + )) + } + + pub fn field_access(container: Expression, field: Node, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::FieldAccess(FieldAccess { + container, + field, + })), + position, + )) + } + + pub fn tuple_access(tuple: Expression, index: Node, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::TupleAccess(TupleAccess { + tuple, + index, + })), + position, + )) + } + + pub fn assignment(assignee: Expression, value: Expression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator( + OperatorExpression::Assignment { assignee, value }, + )), + position, + )) + } + + pub fn comparison( + left: Expression, + operator: Node, + right: Expression, + position: Span, + ) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator( + OperatorExpression::Comparison { + left, + operator, + right, + }, + )), + position, + )) + } + + pub fn compound_assignment( + assignee: Expression, + operator: Node, + modifier: Expression, + position: Span, + ) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator( + OperatorExpression::CompoundAssignment { + assignee, + operator, + modifier, + }, + )), + position, + )) + } + + pub fn math( + left: Expression, + operator: Node, + right: Expression, + position: Span, + ) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Math { + left, + operator, + right, + })), + position, + )) + } + + pub fn negation(expression: Expression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator( + OperatorExpression::Negation(expression), + )), + position, + )) + } + + pub fn not(expression: Expression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Not( + expression, + ))), + position, + )) + } + + pub fn logic( + left: Expression, + operator: Node, + right: Expression, + position: Span, + ) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator( + OperatorExpression::Logic { + left, + operator, + right, + }, + )), + position, + )) + } + + pub fn error_propagation(expression: Expression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator( + OperatorExpression::ErrorPropagation(expression), + )), + position, + )) + } + + pub fn infinite_loop(block: Node, position: Span) -> Self { Expression::WithBlock(Node::new( - Box::new(ExpressionWithBlock::Loop(r#loop)), + Box::new(ExpressionWithBlock::Loop(Loop::Infinite { block })), + position, + )) + } + + pub fn while_loop(condition: Expression, block: Node, position: Span) -> Self { + Expression::WithBlock(Node::new( + Box::new(ExpressionWithBlock::Loop(Loop::While { condition, block })), + position, + )) + } + + pub fn for_loop( + identifier: Node, + iterator: Expression, + block: Node, + position: Span, + ) -> Self { + Expression::WithBlock(Node::new( + Box::new(ExpressionWithBlock::Loop(Loop::For { + identifier, + iterator, + block, + })), position, )) } @@ -168,6 +313,7 @@ pub enum ExpressionWithoutBlock { FieldAccess(FieldAccess), ListIndex(ListIndex), Range(Range), + TupleAccess(TupleAccess), } impl Display for ExpressionWithoutBlock { @@ -183,10 +329,23 @@ impl Display for ExpressionWithoutBlock { ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access), ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index), ExpressionWithoutBlock::Range(range) => write!(f, "{}", range), + ExpressionWithoutBlock::TupleAccess(tuple_access) => write!(f, "{}", tuple_access), } } } +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct TupleAccess { + pub tuple: Expression, + pub index: Node, +} + +impl Display for TupleAccess { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}.{}", self.tuple, self.index) + } +} + #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Range { pub start: Expression, @@ -213,13 +372,13 @@ impl Display for ListIndex { #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct CallExpression { - pub function: Expression, + pub invoker: Expression, pub arguments: Vec, } impl Display for CallExpression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}(", self.function)?; + write!(f, "{}(", self.invoker)?; for (index, argument) in self.arguments.iter().enumerate() { if index > 0 { @@ -342,7 +501,7 @@ pub enum OperatorExpression { CompoundAssignment { assignee: Expression, operator: Node, - value: Expression, + modifier: Expression, }, ErrorPropagation(Expression), Negation(Expression), @@ -375,7 +534,7 @@ impl Display for OperatorExpression { OperatorExpression::CompoundAssignment { assignee, operator, - value, + modifier: value, } => write!(f, "{} {}= {}", assignee, operator, value), OperatorExpression::ErrorPropagation(expression) => write!(f, "{}?", expression), OperatorExpression::Negation(expression) => write!(f, "-{}", expression), @@ -552,7 +711,9 @@ impl Display for Block { #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Loop { - Infinite(Block), + Infinite { + block: Node, + }, While { condition: Expression, block: Node, @@ -560,14 +721,14 @@ pub enum Loop { For { identifier: Node, iterator: Expression, - block: Block, + block: Node, }, } impl Display for Loop { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Loop::Infinite(block) => write!(f, "loop {}", block), + Loop::Infinite { block } => write!(f, "loop {}", block), Loop::While { condition, block } => write!(f, "while {} {}", condition, block), Loop::For { identifier, diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 9f527bf..0bd9a4a 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -298,10 +298,7 @@ impl<'src> Parser<'src> { let operand = self.parse_expression(0)?; let position = (operator_start, self.current_position.1); - Ok(Expression::operator( - OperatorExpression::Not(operand), - position, - )) + Ok(Expression::not(operand, position)) } Token::Minus => { self.next_token()?; @@ -309,10 +306,7 @@ impl<'src> Parser<'src> { let operand = self.parse_expression(0)?; let position = (operator_start, self.current_position.1); - Ok(Expression::operator( - OperatorExpression::Negation(operand), - position, - )) + Ok(Expression::negation(operand, position)) } _ => Err(ParseError::UnexpectedToken { actual: self.current_token.to_owned(), @@ -494,10 +488,7 @@ impl<'src> Parser<'src> { let block = self.parse_block()?; let position = (start_position.0, self.current_position.1); - Ok(Expression::r#loop( - Loop::While { condition, block }, - position, - )) + Ok(Expression::while_loop(condition, block, position)) } _ => Err(ParseError::UnexpectedToken { actual: self.current_token.to_owned(), @@ -523,13 +514,7 @@ impl<'src> Parser<'src> { let value = self.parse_expression(operator_precedence)?; let position = (left_start, value.position().1); - return Ok(Expression::operator( - OperatorExpression::Assignment { - assignee: left, - value, - }, - position, - )); + return Ok(Expression::assignment(left, value, position)); } if let Token::PlusEqual | Token::MinusEqual = &self.current_token { @@ -549,22 +534,7 @@ impl<'src> Parser<'src> { OperatorExpression::CompoundAssignment { assignee: left, operator, - value, - }, - position, - )); - } - - if let Token::Dot = &self.current_token { - self.next_token()?; - - let field = self.parse_identifier()?; - let position = (left_start, self.current_position.1); - - return Ok(Expression::field_access( - FieldAccess { - container: left, - field, + modifier: value, }, position, )); @@ -576,7 +546,7 @@ impl<'src> Parser<'src> { let end = self.parse_expression(operator_precedence)?; let position = (left_start, end.position().1); - return Ok(Expression::range(Range { start: left, end }, position)); + return Ok(Expression::range(left, end, position)); } if let Token::Minus | Token::Plus | Token::Star | Token::Slash | Token::Percent = @@ -673,6 +643,27 @@ impl<'src> Parser<'src> { log::trace!("Parsing {} as postfix operator", self.current_token); let expression = match &self.current_token { + Token::Dot => { + self.next_token()?; + + if let Token::Integer(text) = &self.current_token { + let index = text.parse::().map_err(|error| ParseError::Integer { + error, + position: self.current_position, + })?; + let index_node = Node::new(index, self.current_position); + let position = (left.position().0, self.current_position.1); + + self.next_token()?; + + Expression::tuple_access(left, index_node, position) + } else { + let field = self.parse_identifier()?; + let position = (left.position().0, self.current_position.1); + + Expression::field_access(left, field, position) + } + } Token::LeftCurlyBrace => { let identifier = if let Some(identifier) = left.as_identifier() { identifier @@ -681,7 +672,6 @@ impl<'src> Parser<'src> { }; let name = Node::new(identifier.clone(), left.position()); - let start_left = self.current_position.0; self.next_token()?; @@ -700,7 +690,7 @@ impl<'src> Parser<'src> { self.next_token()?; } else { return Err(ParseError::ExpectedToken { - expected: TokenKind::Equal, + expected: TokenKind::Colon, actual: self.current_token.to_owned(), position: self.current_position, }); @@ -715,7 +705,7 @@ impl<'src> Parser<'src> { } } - let position = (start_left, self.current_position.1); + let position = (left.position().0, self.current_position.1); Expression::r#struct(StructExpression::Fields { name, fields }, position) } @@ -740,17 +730,9 @@ impl<'src> Parser<'src> { let position = (left.position().0, self.current_position.1); - Expression::call( - CallExpression { - function: left, - arguments, - }, - position, - ) + Expression::call(left, arguments, position) } Token::LeftSquareBrace => { - let operator_start = self.current_position.0; - self.next_token()?; let index = self.parse_expression(0)?; @@ -791,7 +773,7 @@ impl<'src> Parser<'src> { fn parse_if(&mut self) -> Result { // Assume that the "if" token has already been consumed - let condition = self.parse_expression(0)?; + let condition = self.parse_expression(10)?; let if_block = self.parse_block()?; if let Token::Else = self.current_token { @@ -1071,24 +1053,20 @@ mod tests { assert_eq!( parse(source), Ok(AbstractSyntaxTree::with_statements([ - Statement::Expression(Expression::field_access( - FieldAccess { - container: Expression::call( - CallExpression { - function: Expression::identifier(Identifier::new("Foo"), (0, 0)), - arguments: vec![ - Expression::literal(LiteralExpression::Integer(42), (0, 0)), - Expression::literal( - LiteralExpression::String("bar".to_string()), - (0, 0) - ), - ], - }, - (0, 0) - ), - field: Node::new(Identifier::new("0"), (0, 0)), - }, - (0, 0) + Statement::Expression(Expression::tuple_access( + Expression::call( + Expression::identifier(Identifier::new("Foo"), (0, 3)), + vec![ + Expression::literal(LiteralExpression::Integer(42), (4, 6)), + Expression::literal( + LiteralExpression::String("bar".to_string()), + (8, 13) + ), + ], + (0, 15) + ), + Node::new(0, (15, 16)), + (0, 16) )) ])) ); @@ -1096,7 +1074,12 @@ mod tests { #[test] fn fields_struct_instantiation() { - let source = "Foo { a = 42, b = 4.0 }"; + let source = "Foo { a: 42, b: 4.0 }"; + let mut tree = AbstractSyntaxTree::new(); + + if parse_into(source, &mut tree).is_err() { + println!("{:?}", tree); + } assert_eq!( parse(source), @@ -1130,19 +1113,19 @@ mod tests { Ok(AbstractSyntaxTree::with_statements([ Statement::struct_definition( StructDefinition::Fields { - name: Node::new(Identifier::new("Foo"), (0, 0)), + name: Node::new(Identifier::new("Foo"), (7, 10)), fields: vec![ ( - Node::new(Identifier::new("a"), (0, 0)), - Node::new(Type::Integer, (0, 0)) + Node::new(Identifier::new("a"), (13, 14)), + Node::new(Type::Integer, (16, 19)) ), ( - Node::new(Identifier::new("b"), (0, 0)), - Node::new(Type::Float, (0, 0)) + Node::new(Identifier::new("b"), (21, 22)), + Node::new(Type::Float, (24, 29)) ) ] }, - (0, 0) + (0, 31) ) ])) ); @@ -1166,13 +1149,11 @@ mod tests { (0, 22) ), Statement::Expression(Expression::call( - CallExpression { - function: Expression::identifier(Identifier::new("Foo"), (23, 26)), - arguments: vec![ - Expression::literal(LiteralExpression::Integer(1), (27, 28)), - Expression::literal(LiteralExpression::Float(2.0), (30, 33)) - ] - }, + Expression::identifier(Identifier::new("Foo"), (23, 26)), + vec![ + Expression::literal(LiteralExpression::Integer(1), (27, 28)), + Expression::literal(LiteralExpression::Float(2.0), (30, 33)) + ], (23, 34) )) ])) @@ -1230,25 +1211,25 @@ mod tests { ListIndex { list: Expression::list( ListExpression::Ordered(vec![ - Expression::literal(LiteralExpression::Integer(1), (0, 0)), + Expression::literal(LiteralExpression::Integer(1), (1, 2)), Expression::list( ListExpression::Ordered(vec![Expression::literal( LiteralExpression::Integer(2), - (0, 0) + (5, 6) )]), - (0, 0) + (4, 7) ), - Expression::literal(LiteralExpression::Integer(3), (0, 0)), + Expression::literal(LiteralExpression::Integer(3), (9, 10)), ]), - (0, 0) + (0, 11) ), - index: Expression::literal(LiteralExpression::Integer(1), (0, 0)), + index: Expression::literal(LiteralExpression::Integer(1), (12, 13)), }, - (0, 0) + (0, 14) ), - index: Expression::literal(LiteralExpression::Integer(0), (0, 0)), + index: Expression::literal(LiteralExpression::Integer(0), (15, 16)), }, - (0, 0) + (0, 17) )) ])) ); @@ -1262,10 +1243,8 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::range( - Range { - start: Expression::literal(LiteralExpression::Integer(0), (0, 1)), - end: Expression::literal(LiteralExpression::Integer(42), (3, 5)), - }, + Expression::literal(LiteralExpression::Integer(0), (0, 1)), + Expression::literal(LiteralExpression::Integer(42), (3, 5)), (0, 5) )) ])) @@ -1478,37 +1457,29 @@ mod tests { assert_eq!( parse(source), Ok(AbstractSyntaxTree::with_statements([ - Statement::Expression(Expression::r#loop( - Loop::While { - condition: Expression::operator( - OperatorExpression::Comparison { - left: Expression::identifier(Identifier::new("x"), (6, 7)), - operator: Node::new(ComparisonOperator::LessThan, (8, 9)), - right: Expression::literal( - LiteralExpression::Integer(10), - (10, 12) + Statement::Expression(Expression::while_loop( + Expression::operator( + OperatorExpression::Comparison { + left: Expression::identifier(Identifier::new("x"), (6, 7)), + operator: Node::new(ComparisonOperator::LessThan, (8, 9)), + right: Expression::literal(LiteralExpression::Integer(10), (10, 12)), + }, + (6, 12) + ), + Node::new( + Block::Sync(vec![Statement::Expression(Expression::operator( + OperatorExpression::CompoundAssignment { + assignee: Expression::identifier(Identifier::new("x"), (15, 16)), + operator: Node::new(MathOperator::Add, (17, 19)), + modifier: Expression::literal( + LiteralExpression::Integer(1), + (20, 21) ), }, - (6, 12) - ), - block: Node::new( - Block::Sync(vec![Statement::Expression(Expression::operator( - OperatorExpression::CompoundAssignment { - assignee: Expression::identifier( - Identifier::new("x"), - (15, 16) - ), - operator: Node::new(MathOperator::Add, (17, 19)), - value: Expression::literal( - LiteralExpression::Integer(1), - (20, 21) - ), - }, - (15, 21) - ))]), - (13, 23) - ) - }, + (15, 21) + ))]), + (13, 23) + ), (0, 23) )) ])) @@ -1523,18 +1494,12 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::operator( - OperatorExpression::Assignment { - assignee: Expression::identifier(Identifier::new("a"), (0, 0)), - value: Expression::operator( - OperatorExpression::Math { - left: Expression::identifier(Identifier::new("a"), (0, 0)), - operator: Node::new(MathOperator::Add, (0, 0)), - right: Expression::literal(LiteralExpression::Integer(1), (0, 0)), - }, - (0, 0) - ), + OperatorExpression::CompoundAssignment { + assignee: Expression::identifier(Identifier::new("a"), (0, 1)), + operator: Node::new(MathOperator::Add, (2, 4)), + modifier: Expression::literal(LiteralExpression::Integer(1), (5, 6)), }, - (0, 0) + (0, 6) )) ])) ) @@ -1569,13 +1534,13 @@ mod tests { Statement::Expression(Expression::block( Block::Sync(vec![Statement::Expression(Expression::operator( OperatorExpression::Math { - left: Expression::literal(LiteralExpression::Integer(40), (0, 0)), - operator: Node::new(MathOperator::Add, (0, 0)), - right: Expression::literal(LiteralExpression::Integer(2), (0, 0)), + left: Expression::literal(LiteralExpression::Integer(40), (2, 4)), + operator: Node::new(MathOperator::Add, (5, 6)), + right: Expression::literal(LiteralExpression::Integer(2), (7, 8)), }, - (0, 0) + (2, 8) ))]), - (0, 0) + (0, 10) )) ])) ) @@ -1649,10 +1614,10 @@ mod tests { Statement::Expression(Expression::operator( OperatorExpression::Math { left: Expression::literal(LiteralExpression::Integer(42), (0, 2)), - operator: Node::new(MathOperator::Divide, (3, 4)), - right: Expression::literal(LiteralExpression::Integer(2), (5, 6)), + operator: Node::new(MathOperator::Divide, (3, 5)), + right: Expression::literal(LiteralExpression::Integer(2), (6, 8)), }, - (0, 6), + (0, 8), )) ])) ); @@ -1687,10 +1652,10 @@ mod tests { Statement::Expression(Expression::operator( OperatorExpression::Comparison { left: Expression::literal(LiteralExpression::Integer(1), (0, 1)), - operator: Node::new(ComparisonOperator::LessThanOrEqual, (2, 3)), - right: Expression::literal(LiteralExpression::Integer(2), (4, 5)), + operator: Node::new(ComparisonOperator::LessThanOrEqual, (2, 4)), + right: Expression::literal(LiteralExpression::Integer(2), (5, 6)), }, - (0, 5), + (0, 6), )) ])) ); @@ -1706,10 +1671,10 @@ mod tests { Statement::Expression(Expression::operator( OperatorExpression::Comparison { left: Expression::literal(LiteralExpression::Integer(1), (0, 1)), - operator: Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 3)), - right: Expression::literal(LiteralExpression::Integer(2), (4, 5)), + operator: Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 4)), + right: Expression::literal(LiteralExpression::Integer(2), (5, 6)), }, - (0, 5), + (0, 6), )) ])) ); @@ -1763,7 +1728,7 @@ mod tests { Statement::Expression(Expression::operator( OperatorExpression::Math { left: Expression::literal(LiteralExpression::Integer(42), (0, 2)), - operator: Node::new(MathOperator::Divide, (3, 4)), + operator: Node::new(MathOperator::Modulo, (3, 4)), right: Expression::literal(LiteralExpression::Integer(2), (5, 6)), }, (0, 6), @@ -1879,10 +1844,8 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::field_access( - FieldAccess { - container: Expression::identifier(Identifier::new("a"), (0, 1)), - field: Node::new(Identifier::new("b"), (2, 3)), - }, + Expression::identifier(Identifier::new("a"), (0, 1)), + Node::new(Identifier::new("b"), (2, 3)), (0, 3) )) ])) diff --git a/dust-lang/src/token.rs b/dust-lang/src/token.rs index 4fe58b7..64a679a 100644 --- a/dust-lang/src/token.rs +++ b/dust-lang/src/token.rs @@ -238,9 +238,10 @@ impl<'src> Token<'src> { pub fn precedence(&self) -> u8 { match self { - Token::Dot => 10, - Token::LeftParenthesis | Token::LeftSquareBrace => 9, - Token::Star | Token::Slash | Token::Percent => 8, + Token::Identifier(_) => 10, + Token::Dot => 9, + Token::LeftCurlyBrace | Token::LeftParenthesis | Token::LeftSquareBrace => 8, + Token::Star | Token::Slash | Token::Percent => 7, Token::Minus | Token::Plus => 6, Token::DoubleEqual | Token::Less @@ -249,8 +250,8 @@ impl<'src> Token<'src> { | Token::GreaterEqual => 5, Token::DoubleAmpersand => 4, Token::DoublePipe => 3, - Token::Equal | Token::MinusEqual | Token::PlusEqual => 2, - Token::DoubleDot => 1, + Token::DoubleDot => 2, + Token::Equal | Token::MinusEqual | Token::PlusEqual => 1, _ => 0, } } @@ -258,7 +259,8 @@ impl<'src> Token<'src> { pub fn is_left_associative(&self) -> bool { matches!( self, - Token::DoubleAmpersand + Token::Dot + | Token::DoubleAmpersand | Token::DoublePipe | Token::Plus | Token::Minus @@ -269,7 +271,7 @@ impl<'src> Token<'src> { } pub fn is_right_associative(&self) -> bool { - matches!(self, Token::Equal | Token::PlusEqual) + matches!(self, Token::Equal | Token::MinusEqual | Token::PlusEqual) } pub fn is_prefix(&self) -> bool { @@ -277,7 +279,10 @@ impl<'src> Token<'src> { } pub fn is_postfix(&self) -> bool { - matches!(self, Token::LeftParenthesis | Token::LeftSquareBrace) + matches!( + self, + Token::Dot | Token::LeftCurlyBrace | Token::LeftParenthesis | Token::LeftSquareBrace + ) } }