mirror of
https://github.com/danog/parser.git
synced 2025-01-22 21:11:55 +01:00
parser: support static closures
This commit is contained in:
parent
0146d3e1d1
commit
0145e58834
@ -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>,
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user