parser: support declare statement with postfix block

This commit is contained in:
Ryan Chandler 2022-09-13 00:59:12 +01:00
parent bbfce83894
commit d9d3ffbb47
No known key found for this signature in database
GPG Key ID: F113BCADDB3B0CCA
2 changed files with 56 additions and 24 deletions

View File

@ -302,6 +302,7 @@ pub enum Statement {
},
Declare {
declares: Vec<DeclareItem>,
body: Block,
},
Noop,
}

View File

@ -1,7 +1,7 @@
use crate::{
ast::{
Arg, ArrayItem, BackedEnumType, ClassFlag, ClosureUse, ElseIf, IncludeKind, MagicConst,
MethodFlag, StaticVar, Use, UseKind, DeclareItem,
Arg, ArrayItem, BackedEnumType, ClassFlag, ClosureUse, DeclareItem, ElseIf, IncludeKind,
MagicConst, MethodFlag, StaticVar, Use, UseKind,
},
Block, Case, Catch, Expression, Identifier, MatchArm, Program, Statement, Type,
};
@ -190,10 +190,19 @@ impl Parser {
}
self.rparen()?;
self.semi()?;
Statement::Declare { declares }
},
let body = if self.current.kind == TokenKind::LeftBrace {
self.next();
let b = self.block(&TokenKind::RightBrace)?;
self.rbrace()?;
b
} else {
self.semi()?;
vec![]
};
Statement::Declare { declares, body }
}
TokenKind::Global => {
self.next();
@ -2176,7 +2185,9 @@ impl Display for ParseError {
mod tests {
use super::Parser;
use crate::{
ast::{Arg, ArrayItem, ElseIf, IncludeKind, InfixOp, MethodFlag, PropertyFlag, DeclareItem},
ast::{
Arg, ArrayItem, DeclareItem, ElseIf, IncludeKind, InfixOp, MethodFlag, PropertyFlag,
},
Catch, Expression, Identifier, Param, Statement, Type,
};
use trunk_lexer::Lexer;
@ -3365,34 +3376,54 @@ mod tests {
#[test]
fn basic_declare() {
assert_ast("<?php declare(A='B');", &[
Statement::Declare {
declares: vec![
DeclareItem {
key: "A".into(),
value: Expression::ConstantString { value: "B".into() }
}
]
}
]);
assert_ast(
"<?php declare(A='B');",
&[Statement::Declare {
declares: vec![DeclareItem {
key: "A".into(),
value: Expression::ConstantString { value: "B".into() },
}],
body: vec![],
}],
);
}
#[test]
fn multiple_declares_in_single_statement() {
assert_ast("<?php declare(A='B', C='D');", &[
Statement::Declare {
assert_ast(
"<?php declare(A='B', C='D');",
&[Statement::Declare {
declares: vec![
DeclareItem {
key: "A".into(),
value: Expression::ConstantString { value: "B".into() }
value: Expression::ConstantString { value: "B".into() },
},
DeclareItem {
key: "C".into(),
value: Expression::ConstantString { value: "D".into() }
}
]
}
]);
value: Expression::ConstantString { value: "D".into() },
},
],
body: vec![],
}],
);
}
#[test]
fn declare_block() {
assert_ast(
"<?php declare(A='B') { echo 'Hello, world!'; }",
&[Statement::Declare {
declares: vec![DeclareItem {
key: "A".into(),
value: Expression::ConstantString { value: "B".into() },
}],
body: vec![Statement::Echo {
values: vec![Expression::ConstantString {
value: "Hello, world!".into(),
}],
}],
}],
);
}
fn assert_ast(source: &str, expected: &[Statement]) {