Merge pull request #92 from ryangjchandler/feature/braced-variables

This commit is contained in:
Ryan Chandler 2022-09-16 10:23:07 +01:00 committed by GitHub
commit d28b93a4e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 2 deletions

View File

@ -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("<?php ->", &[open!(), TokenKind::Arrow]);
assert_tokens(
"<?php -> $",
&[open!(), TokenKind::Arrow, TokenKind::Dollar],
);
}
#[test]

View File

@ -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 => "*=",

View File

@ -442,6 +442,9 @@ pub enum Expression {
Variable {
name: ByteString,
},
DynamicVariable {
name: Box<Self>,
},
Infix {
lhs: Box<Self>,
op: InfixOp,

View File

@ -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(
"<?php ${'foo'};",
&[expr!(Expression::DynamicVariable {
name: Box::new(Expression::ConstantString {
value: "foo".into()
})
})],
);
assert_ast(
"<?php ${foo()};",
&[expr!(Expression::DynamicVariable {
name: Box::new(Expression::Call {
target: Box::new(Expression::Identifier { name: "foo".into() }),
args: vec![]
})
})],
);
}
fn assert_ast(source: &str, expected: &[Statement]) {
let mut lexer = Lexer::new(None);
let tokens = lexer.tokenize(source).unwrap();