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

View File

@ -1441,10 +1441,6 @@ impl Parser {
self.next(); self.next();
e e
} }
TokenKind::Static => {
self.next();
Expression::Static
}
TokenKind::ConstantString(s) => { TokenKind::ConstantString(s) => {
let e = Expression::ConstantString { value: s.clone() }; let e = Expression::ConstantString { value: s.clone() };
self.next(); self.next();
@ -1583,6 +1579,26 @@ impl Parser {
Expression::Array { items } 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 => { TokenKind::Function => {
self.next(); self.next();
@ -1656,6 +1672,7 @@ impl Parser {
uses, uses,
return_type, return_type,
body, body,
r#static: false,
} }
} }
TokenKind::Fn => { 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]) { fn assert_ast(source: &str, expected: &[Statement]) {
let mut lexer = Lexer::new(None); let mut lexer = Lexer::new(None);
let tokens = lexer.tokenize(source).unwrap(); let tokens = lexer.tokenize(source).unwrap();