diff --git a/trunk_lexer/src/lexer.rs b/trunk_lexer/src/lexer.rs index 5bba1c4..069a0c2 100644 --- a/trunk_lexer/src/lexer.rs +++ b/trunk_lexer/src/lexer.rs @@ -663,7 +663,11 @@ impl Lexer { } } - TokenKind::Variable(buffer.into()) + if buffer.is_empty() { + TokenKind::Dollar + } else { + TokenKind::Variable(buffer.into()) + } } fn tokenize_number( @@ -1066,7 +1070,10 @@ function"#, #[test] fn sigils() { - assert_tokens("", &[open!(), TokenKind::Arrow]); + assert_tokens( + " $", + &[open!(), TokenKind::Arrow, TokenKind::Dollar], + ); } #[test] diff --git a/trunk_lexer/src/token.rs b/trunk_lexer/src/token.rs index 3fc7b0c..47ca78c 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 { + Dollar, HaltCompiler, Readonly, Global, @@ -174,6 +175,7 @@ impl Default for Token { impl Display for TokenKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { + Self::Dollar => "$", Self::HaltCompiler => "__halt_compiler", Self::Readonly => "readonly", Self::AsteriskEqual => "*=", diff --git a/trunk_parser/src/ast.rs b/trunk_parser/src/ast.rs index ab3506a..3e18ca5 100644 --- a/trunk_parser/src/ast.rs +++ b/trunk_parser/src/ast.rs @@ -442,6 +442,9 @@ pub enum Expression { Variable { name: ByteString, }, + DynamicVariable { + name: Box, + }, Infix { lhs: Box, op: InfixOp, diff --git a/trunk_parser/src/parser/mod.rs b/trunk_parser/src/parser/mod.rs index 016a086..5200fa1 100644 --- a/trunk_parser/src/parser/mod.rs +++ b/trunk_parser/src/parser/mod.rs @@ -1930,6 +1930,24 @@ impl Parser { prefix(&op, rhs) } + TokenKind::Dollar => { + self.next(); + + match self.current.kind { + TokenKind::LeftBrace => { + self.next(); + + let name = self.expression(Precedence::Lowest)?; + + self.rbrace()?; + + Expression::DynamicVariable { + name: Box::new(name), + } + } + _ => todo!(), + } + } _ => todo!( "expr lhs: {:?}, line {} col {}", self.current.kind, @@ -4200,6 +4218,28 @@ mod tests { ); } + #[test] + fn braced_variables() { + assert_ast( + "