diff --git a/trunk_lexer/src/lexer.rs b/trunk_lexer/src/lexer.rs index 0960b3a..afa9886 100644 --- a/trunk_lexer/src/lexer.rs +++ b/trunk_lexer/src/lexer.rs @@ -520,6 +520,10 @@ impl Lexer { self.next(); TokenKind::Colon } + &[b'~', ..] => { + self.next(); + TokenKind::BitwiseNot + } &[b, ..] => unimplemented!( " char: {}, line: {}, col: {}", b as char, @@ -766,6 +770,7 @@ impl Lexer { fn identifier_to_keyword(ident: &[u8]) -> Option { Some(match ident { + b"print" => TokenKind::Print, b"__halt_compiler" | b"__HALT_COMPILER" => TokenKind::HaltCompiler, b"readonly" => TokenKind::Readonly, b"global" => TokenKind::Global, diff --git a/trunk_lexer/src/token.rs b/trunk_lexer/src/token.rs index bbc0788..a5e14d2 100644 --- a/trunk_lexer/src/token.rs +++ b/trunk_lexer/src/token.rs @@ -11,6 +11,7 @@ pub enum OpenTagKind { #[derive(Debug, PartialEq, Clone)] pub enum TokenKind { + Print, Dollar, HaltCompiler, Readonly, @@ -161,6 +162,7 @@ pub enum TokenKind { Variable(ByteString), Yield, While, + BitwiseNot, } #[derive(Debug, Clone, PartialEq)] @@ -181,6 +183,8 @@ impl Default for Token { impl Display for TokenKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { + Self::Print => "print", + Self::BitwiseNot => "~", Self::Dollar => "$", Self::HaltCompiler => "__halt_compiler", Self::Readonly => "readonly", diff --git a/trunk_parser/src/ast.rs b/trunk_parser/src/ast.rs index 21abd42..2958778 100644 --- a/trunk_parser/src/ast.rs +++ b/trunk_parser/src/ast.rs @@ -560,7 +560,22 @@ pub enum Expression { value: Box, }, Negate { - value: Box, + value: Box, + }, + UnaryPlus { + value: Box, + }, + BitwiseNot { + value: Box, + }, + PreDecrement { + value: Box, + }, + PreIncrement { + value: Box, + }, + Print { + value: Box, }, Cast { kind: CastKind, diff --git a/trunk_parser/src/parser/mod.rs b/trunk_parser/src/parser/mod.rs index 3288a56..8275860 100644 --- a/trunk_parser/src/parser/mod.rs +++ b/trunk_parser/src/parser/mod.rs @@ -2178,7 +2178,12 @@ fn is_prefix(op: &TokenKind) -> bool { matches!( op, TokenKind::Bang + | TokenKind::Print + | TokenKind::BitwiseNot + | TokenKind::Decrement + | TokenKind::Increment | TokenKind::Minus + | TokenKind::Plus | TokenKind::StringCast | TokenKind::BinaryCast | TokenKind::ObjectCast @@ -2197,12 +2202,27 @@ fn is_prefix(op: &TokenKind) -> bool { fn prefix(op: &TokenKind, rhs: Expression) -> Expression { match op { + TokenKind::Print => Expression::Print { + value: Box::new(rhs), + }, TokenKind::Bang => Expression::BooleanNot { value: Box::new(rhs), }, TokenKind::Minus => Expression::Negate { value: Box::new(rhs), }, + TokenKind::Plus => Expression::UnaryPlus { + value: Box::new(rhs), + }, + TokenKind::BitwiseNot => Expression::BitwiseNot { + value: Box::new(rhs), + }, + TokenKind::Decrement => Expression::PreDecrement { + value: Box::new(rhs), + }, + TokenKind::Increment => Expression::PreIncrement { + value: Box::new(rhs), + }, TokenKind::StringCast | TokenKind::BinaryCast | TokenKind::ObjectCast @@ -4286,6 +4306,56 @@ mod tests { ); } + #[test] + fn unary_plus() { + assert_ast( + "