--- /dev/null
+--TEST--
+Leading commas in function calls is not allowed
+--FILE--
+<?php
+foo(,$foo);
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected ',' in %s on line %d
--- /dev/null
+--TEST--
+Multiple inner commas in function calls is not allowed
+--FILE--
+<?php
+foo($foo,,$bar);
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected ',', expecting ')' in %s on line %d
--- /dev/null
+--TEST--
+Multiple trailing commas in function calls is not allowed
+--FILE--
+<?php
+foo($foo,,);
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected ',', expecting ')' in %s on line %d
--- /dev/null
+--TEST--
+Single comma in function calls is not allowed
+--FILE--
+<?php
+foo(,);
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected ',' in %s on line %d
--- /dev/null
+--TEST--
+Allow trailing commas in function and method calls
+--FILE--
+<?php
+function foo(...$args) {
+ echo __FUNCTION__ . "\n";
+ var_dump($args);
+}
+foo(
+ 'function',
+ 'bar',
+);
+
+class Foo
+{
+ public function __construct(...$args) {
+ echo __FUNCTION__ . "\n";
+ var_dump($args);
+ }
+
+ public function bar(...$args) {
+ echo __FUNCTION__ . "\n";
+ var_dump($args);
+ }
+
+ public function __invoke(...$args) {
+ echo __FUNCTION__ . "\n";
+ var_dump($args);
+ }
+}
+
+$foo = new Foo(
+ 'constructor',
+ 'bar',
+);
+
+$foo->bar(
+ 'method',
+ 'bar',
+);
+
+$foo(
+ 'invoke',
+ 'bar',
+);
+
+$bar = function(...$args) {
+ echo __FUNCTION__ . "\n";
+ var_dump($args);
+};
+
+$bar(
+ 'closure',
+ 'bar',
+);
+
+# Make sure to hit the "not really a function" language constructs
+unset($foo, $bar,);
+var_dump(isset($foo, $bar,));
+?>
+--EXPECT--
+foo
+array(2) {
+ [0]=>
+ string(8) "function"
+ [1]=>
+ string(3) "bar"
+}
+__construct
+array(2) {
+ [0]=>
+ string(11) "constructor"
+ [1]=>
+ string(3) "bar"
+}
+bar
+array(2) {
+ [0]=>
+ string(6) "method"
+ [1]=>
+ string(3) "bar"
+}
+__invoke
+array(2) {
+ [0]=>
+ string(6) "invoke"
+ [1]=>
+ string(3) "bar"
+}
+{closure}
+array(2) {
+ [0]=>
+ string(7) "closure"
+ [1]=>
+ string(3) "bar"
+}
+bool(false)
| T_ECHO echo_expr_list ';' { $$ = $2; }
| T_INLINE_HTML { $$ = zend_ast_create(ZEND_AST_ECHO, $1); }
| expr ';' { $$ = $1; }
- | T_UNSET '(' unset_variables ')' ';' { $$ = $3; }
+ | T_UNSET '(' unset_variables possible_comma ')' ';' { $$ = $3; }
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
{ $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $5, NULL, $7); }
| T_FOREACH '(' expr T_AS foreach_variable T_DOUBLE_ARROW foreach_variable ')'
argument_list:
'(' ')' { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); }
- | '(' non_empty_argument_list ')' { $$ = $2; }
+ | '(' non_empty_argument_list possible_comma ')' { $$ = $2; }
;
non_empty_argument_list:
internal_functions_in_yacc:
- T_ISSET '(' isset_variables ')' { $$ = $3; }
+ T_ISSET '(' isset_variables possible_comma ')' { $$ = $3; }
| T_EMPTY '(' expr ')' { $$ = zend_ast_create(ZEND_AST_EMPTY, $3); }
| T_INCLUDE expr
{ $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2); }