parser: support static closures

This commit is contained in:
Ryan Chandler 2022-09-15 00:04:27 +01:00
parent 0146d3e1d1
commit 0145e58834
No known key found for this signature in database
GPG Key ID: F113BCADDB3B0CCA
2 changed files with 62 additions and 5 deletions

View File

@ -403,7 +403,6 @@ pub struct Use {
#[derive(Debug, PartialEq, Clone)]
pub enum Expression {
Static,
Empty,
ErrorSuppress {
expr: Box<Self>,
@ -443,6 +442,7 @@ pub enum Expression {
uses: Vec<ClosureUse>,
return_type: Option<Type>,
body: Block,
r#static: bool,
},
ArrowFunction {
params: Vec<Param>,

View File

@ -1441,10 +1441,6 @@ impl Parser {
self.next();
e
}
TokenKind::Static => {
self.next();
Expression::Static
}
TokenKind::ConstantString(s) => {
let e = Expression::ConstantString { value: s.clone() };
self.next();
@ -1583,6 +1579,26 @@ impl Parser {
Expression::Array { items }
}
TokenKind::Static if matches!(self.peek.kind, TokenKind::Function) => {
self.next();
match self.expression(Precedence::Lowest)? {
Expression::Closure {
params,
uses,
return_type,
body,
..
} => Expression::Closure {
params,
uses,
return_type,
body,
r#static: true,
},
_ => unreachable!(),
}
}
TokenKind::Function => {
self.next();
@ -1656,6 +1672,7 @@ impl Parser {
uses,
return_type,
body,
r#static: false,
}
}
TokenKind::Fn => {
@ -3664,6 +3681,46 @@ mod tests {
);
}
#[test]
fn basic_closures() {
assert_ast(
"<?php function () {};",
&[expr!(Expression::Closure {
params: vec![],
uses: vec![],
return_type: None,
body: vec![],
r#static: false
})],
);
}
#[test]
fn arrow_functions() {
assert_ast(
"<?php fn () => null;",
&[expr!(Expression::ArrowFunction {
params: vec![],
return_type: None,
expr: Box::new(Expression::Null)
})],
);
}
#[test]
fn static_closures() {
assert_ast(
"<?php static function () {};",
&[expr!(Expression::Closure {
params: vec![],
uses: vec![],
return_type: None,
body: vec![],
r#static: true
})],
);
}
fn assert_ast(source: &str, expected: &[Statement]) {
let mut lexer = Lexer::new(None);
let tokens = lexer.tokenize(source).unwrap();