Add support for list() in foreach (PHP 5.5)

Example: foreach ($coords as list($x, $y)) { ... }

This change slightly breaks backwards compatability, as it changes the
node structure for the previously existing `list(...) = $foo` assignments.
Those no longer have a dedicated `AssignList` node; instead they are
parsed as a normal `Assign` node with a `List` as `var`. Similarly the
use in `foreach` will generate a `List` for `valueVar`.
This commit is contained in:
nikic 2012-09-07 17:22:43 +02:00
parent 8d218110db
commit f8f1e17e41
7 changed files with 1238 additions and 1163 deletions

View File

@ -1,6 +1,13 @@
Version 0.9.3-dev
-----------------
* [BC] [PHP 5.5] Add support for `list()` destructuring of `foreach` values.
Example: `foreach ($coords as list($x, $y)) { ... }`
This changes the node structure for the previously existing `list(...) = $foo` assignments. Those no longer have a
dedicated `AssignList` node; instead they are parsed as a normal `Assign` node with a `List` as `var`. Similarly the
use in `foreach` will generate a `List` for `valueVar`.
* Fix parsing of `$foo =& new Bar`. It is now properly parsed as `AssignRef` (instead of `Assign`).
Version 0.9.2 (07.07.2012)

View File

@ -189,12 +189,10 @@ statement:
| T_INLINE_HTML { $$ = Stmt_InlineHTML[$1]; }
| expr ';' { $$ = $1; }
| T_UNSET '(' variables_list ')' ';' { $$ = Stmt_Unset[$3]; }
| T_FOREACH '(' expr T_AS variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $5, [keyVar: null, byRef: false, stmts: $7]]; }
| T_FOREACH '(' expr T_AS '&' variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $6, [keyVar: null, byRef: true, stmts: $8]]; }
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW optional_ref variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $8, [keyVar: $5, byRef: $7, stmts: $10]]; }
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $5[0], [keyVar: null, byRef: $5[1], stmts: $7]]; }
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $7[0], [keyVar: $5, byRef: $7[1], stmts: $9]]; }
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt_Declare[$3, $5]; }
| ';' { $$ = array(); /* means: no statement */ }
| T_TRY '{' inner_statement_list '}' catches { $$ = Stmt_TryCatch[$3, $5]; }
@ -342,6 +340,12 @@ new_else_single:
| T_ELSE ':' inner_statement_list { $$ = Stmt_Else[$3]; }
;
foreach_variable:
variable { $$ = array($1, false); }
| '&' variable { $$ = array($2, true); }
| list_expr { $$ = array($1, false); }
;
parameter_list:
non_empty_parameter_list { $$ = $1; }
| /* empty */ { $$ = array(); }
@ -495,7 +499,7 @@ for_expr:
expr:
variable { $$ = $1; }
| T_LIST '(' assignment_list ')' '=' expr { $$ = Expr_AssignList[$3, $6]; }
| list_expr '=' expr { $$ = Expr_Assign[$1, $3]; }
| variable '=' expr { $$ = Expr_Assign[$1, $3]; }
| variable '=' '&' variable { $$ = Expr_AssignRef[$1, $4]; }
| variable '=' '&' new_expr { $$ = Expr_AssignRef[$1, $4]; }
@ -581,6 +585,10 @@ new_expr:
T_NEW class_name_reference ctor_arguments { $$ = Expr_New[$2, $3]; }
;
list_expr:
T_LIST '(' assignment_list ')' { $$ = Expr_List[$3]; }
;
lexical_vars:
/* empty */ { $$ = array(); }
| T_USE '(' lexical_var_list ')' { $$ = $3; }

View File

@ -1,25 +0,0 @@
<?php
/**
* @property array $vars List of variables to assign to
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignList extends PHPParser_Node_Expr
{
/**
* Constructs a list() assignment node.
*
* @param array $vars List of variables to assign to
* @param PHPParser_Node_Expr $expr Expression
* @param array $attributes Additional attributes
*/
public function __construct(array $vars, PHPParser_Node_Expr $expr, array $attributes = array()) {
parent::__construct(
array(
'vars' => $vars,
'expr' => $expr
),
$attributes
);
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* @property array $vars List of variables to assign to
*/
class PHPParser_Node_Expr_List extends PHPParser_Node_Expr
{
/**
* Constructs a list() destructuring node.
*
* @param array $vars List of variables to assign to
* @param array $attributes Additional attributes
*/
public function __construct(array $vars, array $attributes = array()) {
parent::__construct(
array(
'vars' => $vars,
),
$attributes
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -151,43 +151,49 @@ array(
)
)
)
14: Expr_AssignList(
vars: array(
0: Expr_Variable(
name: a
14: Expr_Assign(
var: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
)
)
expr: Expr_Variable(
name: b
)
)
15: Expr_AssignList(
vars: array(
0: Expr_Variable(
name: a
)
1: null
2: Expr_Variable(
name: b
15: Expr_Assign(
var: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
1: null
2: Expr_Variable(
name: b
)
)
)
expr: Expr_Variable(
name: c
)
)
16: Expr_AssignList(
vars: array(
0: Expr_Variable(
name: a
)
1: array(
0: null
1: Expr_Variable(
name: c
16: Expr_Assign(
var: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
1: array(
0: null
1: Expr_Variable(
name: c
)
)
2: Expr_Variable(
name: d
)
)
2: Expr_Variable(
name: d
)
)
expr: Expr_Variable(

View File

@ -7,6 +7,8 @@ foreach ($a as $b) {}
foreach ($a as &$b) {}
foreach ($a as $b => $c) {}
foreach ($a as $b => &$c) {}
foreach ($a as list($a, $b)) {}
foreach ($a as $a => list($b, , $c)) {}
// foreach on expression
foreach (array() as $b) {}
@ -69,6 +71,47 @@ array(
)
)
4: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
1: Expr_Variable(
name: b
)
)
)
)
5: Stmt_Foreach(
keyVar: Expr_Variable(
name: a
)
byRef: false
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_List(
vars: array(
0: Expr_Variable(
name: b
)
1: null
2: Expr_Variable(
name: c
)
)
)
)
6: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(
@ -81,7 +124,7 @@ array(
name: b
)
)
5: Stmt_Foreach(
7: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(