|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-10-26 18:45 UTC] melfar at gmail dot com
Description:
------------
PHP parser doesn't allow for array index operation to be used on a
result of a function call. I propose a patch to allow such a
construction.
Reproduce code:
---------------
<?php
function car_brands() {
return array("chevy", "hummer");
}
print car_brands()[1] . "\n";
?>
Expected result:
----------------
"hummer"
Actual result:
--------------
Parse error: syntax error, unexpected '[' in test.php on line 5
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 01:00:01 2025 UTC |
Not sure how to attach a file. The proposed patch is as follows. --- a/Zend/zend_language_parser.y.orig 2009-10-26 18:13:56.000000000 +0300 +++ b/Zend/zend_language_parser.y 2009-10-26 21:20:19.000000000 +0300 @@ -47,7 +47,7 @@ %} %pure_parser -%expect 2 +%expect 6 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' @@ -874,6 +874,11 @@ variable_class_name: ; base_variable_with_function_calls: + raw_base_variable_with_function_calls { $$ = $1; } + | raw_base_variable_with_function_calls '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } +; + +raw_base_variable_with_function_calls: base_variable { $$ = $1; } | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.u.EA.type = ZEND_PARSED_FUNCTION_CALL; } ;The idea was often discussed, but nobody found a fully satisfying solution, yet. Yours is limited to one array dimension. <?php function foo() { return array(array(42)); } echo foo()[0][0]; ?> Will for instance not work but should be supported. I also think it's likely to cause memory problems in edge cases while I wasn't able to create one in my quick tests. Anyidea aobut the above problem?How about this? <?php function car_brands() { return array("gm" => array("chevy" => 1, "hummer" => 2), "toyota" => array("prius" => 1, "corolla" => 2)); } var_dump(car_brands()["toyota"]["corolla"]); ?> New patch is as follows: --- a/Zend/zend_language_parser.y.orig 2009-10-26 18:13:56.000000000 +0300 +++ b/Zend/zend_language_parser.y 2009-10-27 01:02:08.000000000 +0300 @@ -47,7 +47,7 @@ %} %pure_parser -%expect 2 +%expect 6 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' @@ -874,6 +874,11 @@ variable_class_name: ; base_variable_with_function_calls: + raw_base_variable_with_function_calls { $$ = $1; } + | base_variable_with_function_calls '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } +; + +raw_base_variable_with_function_calls: base_variable { $$ = $1; } | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.u.EA.type = ZEND_PARSED_FUNCTION_CALL; } ;Actually, scratch the previous patch since it only worked on functions . Here is the fixed version, and it also prevents someone from modifying the temporary return value, as in: car_brands()["toyota"]["corolla"] = 4; The patch is as follows: --- a/Zend/zend_language_parser.y.orig 2009-10-26 18:13:56.000000000 +0300 +++ b/Zend/zend_language_parser.y 2009-11-08 02:06:20.000000000 +0300 @@ -47,7 +47,7 @@ %} %pure_parser -%expect 2 +%expect 7 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' @@ -834,6 +834,11 @@ ; variable: + raw_variable { $$ = $1; } + | variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); $$.u.EA.type = ZEND_PARSED_FUNCTION_CALL; } +; + +raw_variable: base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); } object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties { zend_do_pop_object(&$$ TSRMLS_CC); $$.u.EA.type = $1.u.EA.type | ($7.u.EA.type ? $7.u.EA.type : $6.u.EA.type); }