diff --git a/src/main/php/lang/ast/nodes/CallableNewExpression.class.php b/src/main/php/lang/ast/nodes/CallableNewExpression.class.php new file mode 100755 index 0000000..d883a47 --- /dev/null +++ b/src/main/php/lang/ast/nodes/CallableNewExpression.class.php @@ -0,0 +1,16 @@ +type= $type; + $this->line= $line; + } + + /** @return iterable */ + public function children() { return [$this->type]; } +} \ No newline at end of file diff --git a/src/main/php/lang/ast/syntax/PHP.class.php b/src/main/php/lang/ast/syntax/PHP.class.php index dcb7238..ba357ff 100755 --- a/src/main/php/lang/ast/syntax/PHP.class.php +++ b/src/main/php/lang/ast/syntax/PHP.class.php @@ -6,6 +6,7 @@ Braced, BreakStatement, CallableExpression, + CallableNewExpression, CaseLabel, CastExpression, CatchStatement, @@ -321,6 +322,30 @@ public function __construct() { } $parse->expecting('(', 'new arguments'); + + // Resolve ambiguity by looking ahead: `new T(...)` which is a first-class + // callable reference vs. `new T(...$it)` - a call with an unpacked argument + if ('...' === $parse->token->value) { + $dots= $parse->token; + $parse->forward(); + if (')' === $parse->token->value) { + $parse->forward(); + + if (null === $type) { + $class= $this->clazz($parse, null); + $class->annotations= $annotations; + $new= new NewClassExpression($class, null, $token->line); + } else { + $new= new NewExpression($type, null, $token->line); + } + + return new CallableNewExpression($new, $token->line); + } + + $parse->queue[]= $parse->token; + $parse->token= $dots; + } + $arguments= $this->arguments($parse); $parse->expecting(')', 'new arguments'); diff --git a/src/test/php/lang/ast/unittest/parse/InvokeTest.class.php b/src/test/php/lang/ast/unittest/parse/InvokeTest.class.php index c69256f..13c02c1 100755 --- a/src/test/php/lang/ast/unittest/parse/InvokeTest.class.php +++ b/src/test/php/lang/ast/unittest/parse/InvokeTest.class.php @@ -1,6 +1,16 @@ assertParsed( + [new CallableNewExpression(new NewExpression('\\T', null, self::LINE), self::LINE)], + 'new T(...);' + ); + } } \ No newline at end of file