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 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`). * Fix parsing of `$foo =& new Bar`. It is now properly parsed as `AssignRef` (instead of `Assign`).
Version 0.9.2 (07.07.2012) Version 0.9.2 (07.07.2012)

View File

@@ -189,12 +189,10 @@ statement:
| T_INLINE_HTML { $$ = Stmt_InlineHTML[$1]; } | T_INLINE_HTML { $$ = Stmt_InlineHTML[$1]; }
| expr ';' { $$ = $1; } | expr ';' { $$ = $1; }
| T_UNSET '(' variables_list ')' ';' { $$ = Stmt_Unset[$3]; } | T_UNSET '(' variables_list ')' ';' { $$ = Stmt_Unset[$3]; }
| T_FOREACH '(' expr T_AS variable ')' foreach_statement | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $5, [keyVar: null, byRef: false, stmts: $7]]; } { $$ = Stmt_Foreach[$3, $5[0], [keyVar: null, byRef: $5[1], stmts: $7]]; }
| T_FOREACH '(' expr T_AS '&' variable ')' foreach_statement | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $6, [keyVar: null, byRef: true, stmts: $8]]; } { $$ = Stmt_Foreach[$3, $7[0], [keyVar: $5, byRef: $7[1], stmts: $9]]; }
| 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_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt_Declare[$3, $5]; } | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt_Declare[$3, $5]; }
| ';' { $$ = array(); /* means: no statement */ } | ';' { $$ = array(); /* means: no statement */ }
| T_TRY '{' inner_statement_list '}' catches { $$ = Stmt_TryCatch[$3, $5]; } | 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]; } | 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: parameter_list:
non_empty_parameter_list { $$ = $1; } non_empty_parameter_list { $$ = $1; }
| /* empty */ { $$ = array(); } | /* empty */ { $$ = array(); }
@@ -495,7 +499,7 @@ for_expr:
expr: expr:
variable { $$ = $1; } 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 '=' expr { $$ = Expr_Assign[$1, $3]; }
| variable '=' '&' variable { $$ = Expr_AssignRef[$1, $4]; } | variable '=' '&' variable { $$ = Expr_AssignRef[$1, $4]; }
| variable '=' '&' new_expr { $$ = 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]; } T_NEW class_name_reference ctor_arguments { $$ = Expr_New[$2, $3]; }
; ;
list_expr:
T_LIST '(' assignment_list ')' { $$ = Expr_List[$3]; }
;
lexical_vars: lexical_vars:
/* empty */ { $$ = array(); } /* empty */ { $$ = array(); }
| T_USE '(' lexical_var_list ')' { $$ = $3; } | 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( 14: Expr_Assign(
vars: array( var: Expr_List(
0: Expr_Variable( vars: array(
name: a 0: Expr_Variable(
name: a
)
) )
) )
expr: Expr_Variable( expr: Expr_Variable(
name: b name: b
) )
) )
15: Expr_AssignList( 15: Expr_Assign(
vars: array( var: Expr_List(
0: Expr_Variable( vars: array(
name: a 0: Expr_Variable(
) name: a
1: null )
2: Expr_Variable( 1: null
name: b 2: Expr_Variable(
name: b
)
) )
) )
expr: Expr_Variable( expr: Expr_Variable(
name: c name: c
) )
) )
16: Expr_AssignList( 16: Expr_Assign(
vars: array( var: Expr_List(
0: Expr_Variable( vars: array(
name: a 0: Expr_Variable(
) name: a
1: array( )
0: null 1: array(
1: Expr_Variable( 0: null
name: c 1: Expr_Variable(
name: c
)
)
2: Expr_Variable(
name: d
) )
)
2: Expr_Variable(
name: d
) )
) )
expr: Expr_Variable( expr: Expr_Variable(

View File

@@ -7,6 +7,8 @@ foreach ($a as $b) {}
foreach ($a as &$b) {} foreach ($a as &$b) {}
foreach ($a as $b => $c) {} foreach ($a as $b => $c) {}
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 on expression
foreach (array() as $b) {} foreach (array() as $b) {}
@@ -69,6 +71,47 @@ array(
) )
) )
4: Stmt_Foreach( 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 keyVar: null
byRef: false byRef: false
stmts: array( stmts: array(
@@ -81,7 +124,7 @@ array(
name: b name: b
) )
) )
5: Stmt_Foreach( 7: Stmt_Foreach(
keyVar: null keyVar: null
byRef: false byRef: false
stmts: array( stmts: array(