mirror of
https://github.com/danog/parser.git
synced 2024-11-27 04:14:55 +01:00
parent
a502c21a7f
commit
479b323cd9
7
phpast/samples/variadic.php
Normal file
7
phpast/samples/variadic.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
function foo(...$bar) {}
|
||||
|
||||
function bar(string ...$baz) {}
|
||||
|
||||
function baz($foo, $bar, ...$baz) {}
|
@ -345,6 +345,20 @@ impl Lexer {
|
||||
}
|
||||
|
||||
TokenKind::Float(buffer.parse().unwrap())
|
||||
} else if let Some('.') = it.peek() {
|
||||
it.next();
|
||||
|
||||
self.col += 1;
|
||||
|
||||
if let Some('.') = it.peek() {
|
||||
it.next();
|
||||
|
||||
self.col += 1;
|
||||
|
||||
TokenKind::Ellipsis
|
||||
} else {
|
||||
todo!("don't know how to handle this case yet, it should just be 2 Dot tokens...")
|
||||
}
|
||||
} else {
|
||||
TokenKind::Dot
|
||||
}
|
||||
|
@ -41,11 +41,12 @@ pub type ParamList = Vec<Param>;
|
||||
pub struct Param {
|
||||
pub(crate) name: Expression,
|
||||
pub(crate) r#type: Option<Type>,
|
||||
pub(crate) variadic: bool,
|
||||
}
|
||||
|
||||
impl From<String> for Param {
|
||||
fn from(name: String) -> Self {
|
||||
Self { name: Expression::Variable(name), r#type: None }
|
||||
Self { name: Expression::Variable(name), r#type: None, variadic: false }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1332,7 +1332,66 @@ mod tests {
|
||||
params: vec![
|
||||
Param {
|
||||
name: Expression::Variable("b".into()),
|
||||
r#type: Some(Type::Plain("string".into()))
|
||||
r#type: Some(Type::Plain("string".into())),
|
||||
variadic: false,
|
||||
}
|
||||
],
|
||||
body: vec![],
|
||||
return_type: None,
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variadic_params() {
|
||||
assert_ast("<?php function foo(...$bar) {}", &[
|
||||
Statement::Function {
|
||||
name: "foo".to_string().into(),
|
||||
params: vec![
|
||||
Param {
|
||||
name: Expression::Variable("bar".into()),
|
||||
r#type: None,
|
||||
variadic: true,
|
||||
}
|
||||
],
|
||||
body: vec![],
|
||||
return_type: None,
|
||||
}
|
||||
]);
|
||||
|
||||
assert_ast("<?php function foo(string ...$bar) {}", &[
|
||||
Statement::Function {
|
||||
name: "foo".to_string().into(),
|
||||
params: vec![
|
||||
Param {
|
||||
name: Expression::Variable("bar".into()),
|
||||
r#type: Some(Type::Plain("string".into())),
|
||||
variadic: true,
|
||||
}
|
||||
],
|
||||
body: vec![],
|
||||
return_type: None,
|
||||
}
|
||||
]);
|
||||
|
||||
assert_ast("<?php function foo($bar, $baz, ...$car) {}", &[
|
||||
Statement::Function {
|
||||
name: "foo".to_string().into(),
|
||||
params: vec![
|
||||
Param {
|
||||
name: Expression::Variable("bar".into()),
|
||||
r#type: None,
|
||||
variadic: false,
|
||||
},
|
||||
Param {
|
||||
name: Expression::Variable("baz".into()),
|
||||
r#type: None,
|
||||
variadic: false,
|
||||
},
|
||||
Param {
|
||||
name: Expression::Variable("car".into()),
|
||||
r#type: None,
|
||||
variadic: true,
|
||||
}
|
||||
],
|
||||
body: vec![],
|
||||
@ -1349,7 +1408,8 @@ mod tests {
|
||||
params: vec![
|
||||
Param {
|
||||
name: Expression::Variable("b".into()),
|
||||
r#type: Some(Type::Nullable("string".into()))
|
||||
r#type: Some(Type::Nullable("string".into())),
|
||||
variadic: false,
|
||||
}
|
||||
],
|
||||
body: vec![],
|
||||
@ -1369,7 +1429,8 @@ mod tests {
|
||||
r#type: Some(Type::Union(vec![
|
||||
"int".into(),
|
||||
"float".into()
|
||||
]))
|
||||
])),
|
||||
variadic: false,
|
||||
}
|
||||
],
|
||||
body: vec![],
|
||||
@ -1389,7 +1450,8 @@ mod tests {
|
||||
r#type: Some(Type::Intersection(vec![
|
||||
"Foo".into(),
|
||||
"Bar".into()
|
||||
]))
|
||||
])),
|
||||
variadic: false
|
||||
}
|
||||
],
|
||||
body: vec![],
|
||||
|
@ -11,11 +11,16 @@ impl Parser {
|
||||
let mut param_type = None;
|
||||
|
||||
// 1. If we don't see a variable, we should expect a type-string.
|
||||
if ! matches!(self.current.kind, TokenKind::Variable(_)) {
|
||||
if ! matches!(self.current.kind, TokenKind::Variable(_) | TokenKind::Ellipsis) {
|
||||
// 1a. Try to parse the type.
|
||||
param_type = Some(self.type_string()?);
|
||||
}
|
||||
|
||||
let variadic = if self.current.kind == TokenKind::Ellipsis {
|
||||
self.next();
|
||||
true
|
||||
} else { false };
|
||||
|
||||
// 2. Then expect a variable.
|
||||
let var = expect!(self, TokenKind::Variable(v), v, "expected variable");
|
||||
|
||||
@ -23,6 +28,7 @@ impl Parser {
|
||||
params.push(Param {
|
||||
name: Expression::Variable(var),
|
||||
r#type: param_type,
|
||||
variadic
|
||||
});
|
||||
|
||||
if self.current.kind == TokenKind::Comma {
|
||||
|
Loading…
Reference in New Issue
Block a user