From 27d5705f85c5589c69f4ac8b8532d4b39368636a Mon Sep 17 00:00:00 2001 From: Ryan Chandler Date: Fri, 16 Sep 2022 16:16:14 +0100 Subject: [PATCH] parser/lexer: implement all assignment ops --- trunk_lexer/src/lexer.rs | 29 +++++ trunk_lexer/src/token.rs | 12 ++ trunk_parser/src/ast.rs | 14 +++ trunk_parser/src/parser/mod.rs | 175 ++++++++++++++++++++++++++ trunk_parser/src/parser/precedence.rs | 3 +- 5 files changed, 232 insertions(+), 1 deletion(-) diff --git a/trunk_lexer/src/lexer.rs b/trunk_lexer/src/lexer.rs index 203ec60..8c5bf1d 100644 --- a/trunk_lexer/src/lexer.rs +++ b/trunk_lexer/src/lexer.rs @@ -149,6 +149,10 @@ impl Lexer { self.skip(2); TokenKind::BooleanAnd } + [b'&', b'=', ..] => { + self.skip(2); + TokenKind::AmpersandEquals + } [b'&', ..] => { self.next(); TokenKind::Ampersand @@ -363,6 +367,10 @@ impl Lexer { self.next(); TokenKind::Slash } + [b'*', b'*', b'=', ..] => { + self.skip(3); + TokenKind::PowEquals + } [b'*', b'*', ..] => { self.skip(2); TokenKind::Pow @@ -379,10 +387,18 @@ impl Lexer { self.skip(2); TokenKind::Pipe } + [b'|', b'=', ..] => { + self.skip(2); + TokenKind::PipeEquals + } [b'|', ..] => { self.next(); TokenKind::Pipe } + [b'^', b'=', ..] => { + self.skip(2); + TokenKind::CaretEquals + } [b'^', ..] => { self.next(); TokenKind::Caret @@ -458,6 +474,10 @@ impl Lexer { self.next(); TokenKind::Plus } + [b'%', b'=', ..] => { + self.skip(2); + TokenKind::PercentEquals + } [b'%', ..] => { self.next(); TokenKind::Percent @@ -484,6 +504,11 @@ impl Lexer { todo!("heredocs & nowdocs"); } + [b'<', b'<', b'=', ..] => { + self.skip(3); + + TokenKind::LeftShiftEquals + } [b'<', b'<', ..] => { self.skip(2); TokenKind::LeftShift @@ -504,6 +529,10 @@ impl Lexer { self.next(); TokenKind::LessThan } + [b'>', b'>', b'=', ..] => { + self.skip(3); + TokenKind::RightShiftEquals + } [b'>', b'>', ..] => { self.skip(2); TokenKind::RightShift diff --git a/trunk_lexer/src/token.rs b/trunk_lexer/src/token.rs index fee397c..fe4f746 100644 --- a/trunk_lexer/src/token.rs +++ b/trunk_lexer/src/token.rs @@ -18,6 +18,7 @@ pub enum TokenKind { Global, Abstract, Ampersand, + AmpersandEquals, And, AndEqual, Array, @@ -40,6 +41,7 @@ pub enum TokenKind { Break, Callable, Caret, + CaretEquals, Case, Catch, Class, @@ -117,7 +119,9 @@ pub enum TokenKind { LeftBracket, LeftParen, LeftShift, + LeftShiftEquals, RightShift, + RightShiftEquals, LessThan, LessThanEquals, Match, @@ -130,7 +134,9 @@ pub enum TokenKind { UnsetCast, OpenTag(OpenTagKind), Percent, + PercentEquals, Pipe, + PipeEquals, Plus, PlusEquals, Pow, @@ -215,6 +221,7 @@ impl Display for TokenKind { Self::Break => "break", Self::Callable => "callable", Self::Caret => "^", + Self::CaretEquals => "^=", Self::Case => "case", Self::Catch => "catch", Self::Class => "class", @@ -297,6 +304,9 @@ impl Display for TokenKind { Self::LeftBracket => "[", Self::LeftParen => "(", Self::LeftShift => "<<", + Self::LeftShiftEquals => "<<=", + Self::RightShift => ">>", + Self::RightShiftEquals => ">>=", Self::LessThan => "<", Self::LessThanEquals => "<=", Self::Match => "match", @@ -310,7 +320,9 @@ impl Display for TokenKind { OpenTagKind::Full => " "%", + Self::PercentEquals => "%=", Self::Pipe => "|", + Self::PipeEquals => "|=", Self::Plus => "+", Self::PlusEquals => "+=", Self::Pow => "**", diff --git a/trunk_parser/src/ast.rs b/trunk_parser/src/ast.rs index ae3c3d7..d6e4f9b 100644 --- a/trunk_parser/src/ast.rs +++ b/trunk_parser/src/ast.rs @@ -650,6 +650,13 @@ pub enum InfixOp { LogicalOr, LogicalXor, Spaceship, + PowAssign, + ModAssign, + BitwiseAndAssign, + BitwiseOrAssign, + BitwiseXorAssign, + LeftShiftAssign, + RightShiftAssign, } impl From for InfixOp { @@ -689,6 +696,13 @@ impl From for InfixOp { TokenKind::LogicalAnd => Self::LogicalAnd, TokenKind::LogicalOr => Self::LogicalOr, TokenKind::LogicalXor => Self::LogicalXor, + TokenKind::PowEquals => Self::PowAssign, + TokenKind::PercentEquals => Self::ModAssign, + TokenKind::AmpersandEquals => Self::BitwiseAndAssign, + TokenKind::PipeEquals => Self::BitwiseOrAssign, + TokenKind::CaretEquals => Self::BitwiseXorAssign, + TokenKind::LeftShiftEquals => Self::LeftShiftAssign, + TokenKind::RightShiftEquals => Self::RightShiftAssign, _ => unreachable!(), } } diff --git a/trunk_parser/src/parser/mod.rs b/trunk_parser/src/parser/mod.rs index 452b3be..b474ba7 100644 --- a/trunk_parser/src/parser/mod.rs +++ b/trunk_parser/src/parser/mod.rs @@ -2257,6 +2257,13 @@ fn is_infix(t: &TokenKind) -> bool { matches!( t, TokenKind::Pow + | TokenKind::RightShiftEquals + | TokenKind::LeftShiftEquals + | TokenKind::CaretEquals + | TokenKind::AmpersandEquals + | TokenKind::PipeEquals + | TokenKind::PercentEquals + | TokenKind::PowEquals | TokenKind::LogicalAnd | TokenKind::LogicalOr | TokenKind::LogicalXor @@ -4499,6 +4506,174 @@ mod tests { ); } + #[test] + fn assign() { + assert_ast( + ">= 1;", + &[expr!(Expression::Infix { + lhs: Box::new(Expression::Variable { name: "a".into() }), + op: InfixOp::RightShiftAssign, + rhs: Box::new(Expression::Int { i: 1 }), + })], + ); + } + + #[test] + fn null_coalese_assign() { + assert_ast( + " Self::NullCoalesce, Question => Self::Ternary, Equals | PlusEquals | MinusEquals | AsteriskEqual | PowEquals | SlashEquals - | DotEquals | AndEqual | CoalesceEqual => Self::Assignment, + | DotEquals | AndEqual | CoalesceEqual | PercentEquals | AmpersandEquals + | PipeEquals | CaretEquals | LeftShiftEquals | RightShiftEquals => Self::Assignment, Yield => Self::Yield, LogicalAnd => Self::KeyAnd, LogicalOr => Self::KeyOr,