1 %pure_parser 2 %expect 6 3 4 %tokens 5 6 %% 7 8 start: 9 top_statement_list { $$ = $this->handleNamespaces($1); } 10 ; 11 12 top_statement_list_ex: 13 top_statement_list_ex top_statement { pushNormalizing($1, $2); } 14 | /* empty */ { init(); } 15 ; 16 17 top_statement_list: 18 top_statement_list_ex 19 { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); 20 if ($nop !== null) { $1[] = $nop; } $$ = $1; } 21 ; 22 23 ampersand: 24 T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG 25 | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG 26 ; 27 28 reserved_non_modifiers: 29 T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND 30 | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE 31 | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH 32 | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO 33 | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT 34 | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS 35 | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN 36 | T_MATCH 37 ; 38 39 semi_reserved: 40 reserved_non_modifiers 41 | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC 42 ; 43 44 identifier_ex: 45 T_STRING { $$ = Node\Identifier[$1]; } 46 | semi_reserved { $$ = Node\Identifier[$1]; } 47 ; 48 49 identifier: 50 T_STRING { $$ = Node\Identifier[$1]; } 51 ; 52 53 reserved_non_modifiers_identifier: 54 reserved_non_modifiers { $$ = Node\Identifier[$1]; } 55 ; 56 57 namespace_name: 58 T_STRING { $$ = Name[$1]; } 59 | T_NAME_QUALIFIED { $$ = Name[$1]; } 60 ; 61 62 legacy_namespace_name: 63 namespace_name { $$ = $1; } 64 | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } 65 ; 66 67 plain_variable: 68 T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } 69 ; 70 71 top_statement: 72 statement { $$ = $1; } 73 | function_declaration_statement { $$ = $1; } 74 | class_declaration_statement { $$ = $1; } 75 | T_HALT_COMPILER 76 { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } 77 | T_NAMESPACE namespace_name ';' 78 { $$ = Stmt\Namespace_[$2, null]; 79 $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); 80 $this->checkNamespace($$); } 81 | T_NAMESPACE namespace_name '{' top_statement_list '}' 82 { $$ = Stmt\Namespace_[$2, $4]; 83 $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); 84 $this->checkNamespace($$); } 85 | T_NAMESPACE '{' top_statement_list '}' 86 { $$ = Stmt\Namespace_[null, $3]; 87 $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); 88 $this->checkNamespace($$); } 89 | T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } 90 | T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; } 91 | group_use_declaration ';' { $$ = $1; } 92 | T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; } 93 ; 94 95 use_type: 96 T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } 97 | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } 98 ; 99 100 group_use_declaration: 101 T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' 102 { $$ = Stmt\GroupUse[$3, $6, $2]; } 103 | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' 104 { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } 105 ; 106 107 unprefixed_use_declarations: 108 unprefixed_use_declarations ',' unprefixed_use_declaration 109 { push($1, $3); } 110 | unprefixed_use_declaration { init($1); } 111 ; 112 113 use_declarations: 114 use_declarations ',' use_declaration { push($1, $3); } 115 | use_declaration { init($1); } 116 ; 117 118 inline_use_declarations: 119 inline_use_declarations ',' inline_use_declaration { push($1, $3); } 120 | inline_use_declaration { init($1); } 121 ; 122 123 unprefixed_use_declaration: 124 namespace_name 125 { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } 126 | namespace_name T_AS identifier 127 { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } 128 ; 129 130 use_declaration: 131 legacy_namespace_name 132 { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } 133 | legacy_namespace_name T_AS identifier 134 { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } 135 ; 136 137 inline_use_declaration: 138 unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } 139 | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } 140 ; 141 142 constant_declaration_list: 143 constant_declaration_list ',' constant_declaration { push($1, $3); } 144 | constant_declaration { init($1); } 145 ; 146 147 constant_declaration: 148 identifier '=' static_scalar { $$ = Node\Const_[$1, $3]; } 149 ; 150 151 class_const_list: 152 class_const_list ',' class_const { push($1, $3); } 153 | class_const { init($1); } 154 ; 155 156 class_const: 157 identifier_ex '=' static_scalar { $$ = Node\Const_[$1, $3]; } 158 ; 159 160 inner_statement_list_ex: 161 inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } 162 | /* empty */ { init(); } 163 ; 164 165 inner_statement_list: 166 inner_statement_list_ex 167 { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); 168 if ($nop !== null) { $1[] = $nop; } $$ = $1; } 169 ; 170 171 inner_statement: 172 statement { $$ = $1; } 173 | function_declaration_statement { $$ = $1; } 174 | class_declaration_statement { $$ = $1; } 175 | T_HALT_COMPILER 176 { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } 177 ; 178 179 non_empty_statement: 180 '{' inner_statement_list '}' 181 { 182 if ($2) { 183 $$ = $2; prependLeadingComments($$); 184 } else { 185 makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); 186 if (null === $$) { $$ = array(); } 187 } 188 } 189 | T_IF parentheses_expr statement elseif_list else_single 190 { $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; } 191 | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' 192 { $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; } 193 | T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; } 194 | T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; } 195 | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement 196 { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } 197 | T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; } 198 | T_BREAK ';' { $$ = Stmt\Break_[null]; } 199 | T_BREAK expr ';' { $$ = Stmt\Break_[$2]; } 200 | T_CONTINUE ';' { $$ = Stmt\Continue_[null]; } 201 | T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; } 202 | T_RETURN ';' { $$ = Stmt\Return_[null]; } 203 | T_RETURN expr ';' { $$ = Stmt\Return_[$2]; } 204 | T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; } 205 | T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; } 206 | T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; } 207 | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } 208 | yield_expr ';' { $$ = Stmt\Expression[$1]; } 209 | expr ';' { $$ = Stmt\Expression[$1]; } 210 | T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; } 211 | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement 212 { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } 213 | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement 214 { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } 215 | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } 216 | T_TRY '{' inner_statement_list '}' catches optional_finally 217 { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } 218 | T_THROW expr ';' { $$ = Stmt\Throw_[$2]; } 219 | T_GOTO identifier ';' { $$ = Stmt\Goto_[$2]; } 220 | identifier ':' { $$ = Stmt\Label[$1]; } 221 | expr error { $$ = Stmt\Expression[$1]; } 222 | error { $$ = array(); /* means: no statement */ } 223 ; 224 225 statement: 226 non_empty_statement { $$ = $1; } 227 | ';' 228 { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); 229 if ($$ === null) $$ = array(); /* means: no statement */ } 230 ; 231 232 catches: 233 /* empty */ { init(); } 234 | catches catch { push($1, $2); } 235 ; 236 237 catch: 238 T_CATCH '(' name plain_variable ')' '{' inner_statement_list '}' 239 { $$ = Stmt\Catch_[array($3), $4, $7]; } 240 ; 241 242 optional_finally: 243 /* empty */ { $$ = null; } 244 | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } 245 ; 246 247 variables_list: 248 variable { init($1); } 249 | variables_list ',' variable { push($1, $3); } 250 ; 251 252 optional_ref: 253 /* empty */ { $$ = false; } 254 | ampersand { $$ = true; } 255 ; 256 257 optional_arg_ref: 258 /* empty */ { $$ = false; } 259 | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; } 260 ; 261 262 optional_ellipsis: 263 /* empty */ { $$ = false; } 264 | T_ELLIPSIS { $$ = true; } 265 ; 266 267 function_declaration_statement: 268 T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' 269 { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } 270 ; 271 272 class_declaration_statement: 273 class_entry_type identifier extends_from implements_list '{' class_statement_list '}' 274 { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; 275 $this->checkClass($$, #2); } 276 | T_INTERFACE identifier interface_extends_list '{' class_statement_list '}' 277 { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; 278 $this->checkInterface($$, #2); } 279 | T_TRAIT identifier '{' class_statement_list '}' 280 { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; } 281 ; 282 283 class_entry_type: 284 T_CLASS { $$ = 0; } 285 | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } 286 | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } 287 ; 288 289 extends_from: 290 /* empty */ { $$ = null; } 291 | T_EXTENDS class_name { $$ = $2; } 292 ; 293 294 interface_extends_list: 295 /* empty */ { $$ = array(); } 296 | T_EXTENDS class_name_list { $$ = $2; } 297 ; 298 299 implements_list: 300 /* empty */ { $$ = array(); } 301 | T_IMPLEMENTS class_name_list { $$ = $2; } 302 ; 303 304 class_name_list: 305 class_name { init($1); } 306 | class_name_list ',' class_name { push($1, $3); } 307 ; 308 309 for_statement: 310 statement { $$ = toArray($1); } 311 | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } 312 ; 313 314 foreach_statement: 315 statement { $$ = toArray($1); } 316 | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } 317 ; 318 319 declare_statement: 320 non_empty_statement { $$ = toArray($1); } 321 | ';' { $$ = null; } 322 | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } 323 ; 324 325 declare_list: 326 declare_list_element { init($1); } 327 | declare_list ',' declare_list_element { push($1, $3); } 328 ; 329 330 declare_list_element: 331 identifier '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; } 332 ; 333 334 switch_case_list: 335 '{' case_list '}' { $$ = $2; } 336 | '{' ';' case_list '}' { $$ = $3; } 337 | ':' case_list T_ENDSWITCH ';' { $$ = $2; } 338 | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } 339 ; 340 341 case_list: 342 /* empty */ { init(); } 343 | case_list case { push($1, $2); } 344 ; 345 346 case: 347 T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } 348 | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } 349 ; 350 351 case_separator: 352 ':' 353 | ';' 354 ; 355 356 while_statement: 357 statement { $$ = toArray($1); } 358 | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } 359 ; 360 361 elseif_list: 362 /* empty */ { init(); } 363 | elseif_list elseif { push($1, $2); } 364 ; 365 366 elseif: 367 T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; } 368 ; 369 370 new_elseif_list: 371 /* empty */ { init(); } 372 | new_elseif_list new_elseif { push($1, $2); } 373 ; 374 375 new_elseif: 376 T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; } 377 ; 378 379 else_single: 380 /* empty */ { $$ = null; } 381 | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } 382 ; 383 384 new_else_single: 385 /* empty */ { $$ = null; } 386 | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } 387 ; 388 389 foreach_variable: 390 variable { $$ = array($1, false); } 391 | ampersand variable { $$ = array($2, true); } 392 | list_expr { $$ = array($1, false); } 393 ; 394 395 parameter_list: 396 non_empty_parameter_list { $$ = $1; } 397 | /* empty */ { $$ = array(); } 398 ; 399 400 non_empty_parameter_list: 401 parameter { init($1); } 402 | non_empty_parameter_list ',' parameter { push($1, $3); } 403 ; 404 405 parameter: 406 optional_param_type optional_arg_ref optional_ellipsis plain_variable 407 { $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); } 408 | optional_param_type optional_arg_ref optional_ellipsis plain_variable '=' static_scalar 409 { $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); } 410 ; 411 412 type: 413 name { $$ = $1; } 414 | T_ARRAY { $$ = Node\Identifier['array']; } 415 | T_CALLABLE { $$ = Node\Identifier['callable']; } 416 ; 417 418 optional_param_type: 419 /* empty */ { $$ = null; } 420 | type { $$ = $1; } 421 ; 422 423 optional_return_type: 424 /* empty */ { $$ = null; } 425 | ':' type { $$ = $2; } 426 ; 427 428 argument_list: 429 '(' ')' { $$ = array(); } 430 | '(' non_empty_argument_list ')' { $$ = $2; } 431 | '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); } 432 ; 433 434 non_empty_argument_list: 435 argument { init($1); } 436 | non_empty_argument_list ',' argument { push($1, $3); } 437 ; 438 439 argument: 440 expr { $$ = Node\Arg[$1, false, false]; } 441 | ampersand variable { $$ = Node\Arg[$2, true, false]; } 442 | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } 443 ; 444 445 global_var_list: 446 global_var_list ',' global_var { push($1, $3); } 447 | global_var { init($1); } 448 ; 449 450 global_var: 451 plain_variable { $$ = $1; } 452 | '$' variable { $$ = Expr\Variable[$2]; } 453 | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } 454 ; 455 456 static_var_list: 457 static_var_list ',' static_var { push($1, $3); } 458 | static_var { init($1); } 459 ; 460 461 static_var: 462 plain_variable { $$ = Stmt\StaticVar[$1, null]; } 463 | plain_variable '=' static_scalar { $$ = Stmt\StaticVar[$1, $3]; } 464 ; 465 466 class_statement_list_ex: 467 class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } 468 | /* empty */ { init(); } 469 ; 470 471 class_statement_list: 472 class_statement_list_ex 473 { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); 474 if ($nop !== null) { $1[] = $nop; } $$ = $1; } 475 ; 476 477 class_statement: 478 variable_modifiers property_declaration_list ';' 479 { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); } 480 | T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2, 0]; } 481 | method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body 482 { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; 483 $this->checkClassMethod($$, #1); } 484 | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } 485 ; 486 487 trait_adaptations: 488 ';' { $$ = array(); } 489 | '{' trait_adaptation_list '}' { $$ = $2; } 490 ; 491 492 trait_adaptation_list: 493 /* empty */ { init(); } 494 | trait_adaptation_list trait_adaptation { push($1, $2); } 495 ; 496 497 trait_adaptation: 498 trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' 499 { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } 500 | trait_method_reference T_AS member_modifier identifier_ex ';' 501 { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } 502 | trait_method_reference T_AS member_modifier ';' 503 { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } 504 | trait_method_reference T_AS identifier ';' 505 { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } 506 | trait_method_reference T_AS reserved_non_modifiers_identifier ';' 507 { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } 508 ; 509 510 trait_method_reference_fully_qualified: 511 name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = array($1, $3); } 512 ; 513 trait_method_reference: 514 trait_method_reference_fully_qualified { $$ = $1; } 515 | identifier_ex { $$ = array(null, $1); } 516 ; 517 518 method_body: 519 ';' /* abstract method */ { $$ = null; } 520 | '{' inner_statement_list '}' { $$ = $2; } 521 ; 522 523 variable_modifiers: 524 non_empty_member_modifiers { $$ = $1; } 525 | T_VAR { $$ = 0; } 526 ; 527 528 method_modifiers: 529 /* empty */ { $$ = 0; } 530 | non_empty_member_modifiers { $$ = $1; } 531 ; 532 533 non_empty_member_modifiers: 534 member_modifier { $$ = $1; } 535 | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } 536 ; 537 538 member_modifier: 539 T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } 540 | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } 541 | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } 542 | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } 543 | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } 544 | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } 545 ; 546 547 property_declaration_list: 548 property_declaration { init($1); } 549 | property_declaration_list ',' property_declaration { push($1, $3); } 550 ; 551 552 property_decl_name: 553 T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } 554 ; 555 556 property_declaration: 557 property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } 558 | property_decl_name '=' static_scalar { $$ = Stmt\PropertyProperty[$1, $3]; } 559 ; 560 561 expr_list: 562 expr_list ',' expr { push($1, $3); } 563 | expr { init($1); } 564 ; 565 566 for_expr: 567 /* empty */ { $$ = array(); } 568 | expr_list { $$ = $1; } 569 ; 570 571 expr: 572 variable { $$ = $1; } 573 | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } 574 | variable '=' expr { $$ = Expr\Assign[$1, $3]; } 575 | variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; } 576 | variable '=' ampersand new_expr { $$ = Expr\AssignRef[$1, $4]; } 577 | new_expr { $$ = $1; } 578 | T_CLONE expr { $$ = Expr\Clone_[$2]; } 579 | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } 580 | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } 581 | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } 582 | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } 583 | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } 584 | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } 585 | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } 586 | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } 587 | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } 588 | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } 589 | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } 590 | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } 591 | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } 592 | variable T_INC { $$ = Expr\PostInc[$1]; } 593 | T_INC variable { $$ = Expr\PreInc [$2]; } 594 | variable T_DEC { $$ = Expr\PostDec[$1]; } 595 | T_DEC variable { $$ = Expr\PreDec [$2]; } 596 | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } 597 | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } 598 | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } 599 | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } 600 | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } 601 | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } 602 | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } 603 | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } 604 | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } 605 | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } 606 | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } 607 | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } 608 | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } 609 | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } 610 | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } 611 | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } 612 | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } 613 | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } 614 | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } 615 | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } 616 | '!' expr { $$ = Expr\BooleanNot[$2]; } 617 | '~' expr { $$ = Expr\BitwiseNot[$2]; } 618 | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } 619 | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } 620 | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } 621 | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } 622 | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } 623 | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } 624 | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } 625 | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } 626 | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } 627 | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } 628 | parentheses_expr { $$ = $1; } 629 /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */ 630 | '(' new_expr ')' { $$ = $2; } 631 | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } 632 | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } 633 | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } 634 | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } 635 | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } 636 | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } 637 | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } 638 | T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; } 639 | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } 640 | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } 641 | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } 642 | T_DOUBLE_CAST expr 643 { $attrs = attributes(); 644 $attrs['kind'] = $this->getFloatCastKind($1); 645 $$ = new Expr\Cast\Double($2, $attrs); } 646 | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } 647 | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } 648 | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } 649 | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } 650 | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } 651 | T_EXIT exit_expr 652 { $attrs = attributes(); 653 $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; 654 $$ = new Expr\Exit_($2, $attrs); } 655 | '@' expr { $$ = Expr\ErrorSuppress[$2]; } 656 | scalar { $$ = $1; } 657 | array_expr { $$ = $1; } 658 | scalar_dereference { $$ = $1; } 659 | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } 660 | T_PRINT expr { $$ = Expr\Print_[$2]; } 661 | T_YIELD { $$ = Expr\Yield_[null, null]; } 662 | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } 663 | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type 664 '{' inner_statement_list '}' 665 { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } 666 | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type 667 '{' inner_statement_list '}' 668 { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } 669 ; 670 671 parentheses_expr: 672 '(' expr ')' { $$ = $2; } 673 | '(' yield_expr ')' { $$ = $2; } 674 ; 675 676 yield_expr: 677 T_YIELD expr { $$ = Expr\Yield_[$2, null]; } 678 | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } 679 ; 680 681 array_expr: 682 T_ARRAY '(' array_pair_list ')' 683 { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; 684 $$ = new Expr\Array_($3, $attrs); } 685 | '[' array_pair_list ']' 686 { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; 687 $$ = new Expr\Array_($2, $attrs); } 688 ; 689 690 scalar_dereference: 691 array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 692 | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' 693 { $attrs = attributes(); $attrs['kind'] = strKind($1); 694 $$ = Expr\ArrayDimFetch[new Scalar\String_(Scalar\String_::parse($1), $attrs), $3]; } 695 | constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 696 | scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 697 /* alternative array syntax missing intentionally */ 698 ; 699 700 anonymous_class: 701 T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' 702 { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); 703 $this->checkClass($$[0], -1); } 704 ; 705 706 new_expr: 707 T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } 708 | T_NEW anonymous_class 709 { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } 710 ; 711 712 lexical_vars: 713 /* empty */ { $$ = array(); } 714 | T_USE '(' lexical_var_list ')' { $$ = $3; } 715 ; 716 717 lexical_var_list: 718 lexical_var { init($1); } 719 | lexical_var_list ',' lexical_var { push($1, $3); } 720 ; 721 722 lexical_var: 723 optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } 724 ; 725 726 function_call: 727 name argument_list { $$ = Expr\FuncCall[$1, $2]; } 728 | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex argument_list 729 { $$ = Expr\StaticCall[$1, $3, $4]; } 730 | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list 731 { $$ = Expr\StaticCall[$1, $4, $6]; } 732 | static_property argument_list 733 { $$ = $this->fixupPhp5StaticPropCall($1, $2, attributes()); } 734 | variable_without_objects argument_list 735 { $$ = Expr\FuncCall[$1, $2]; } 736 | function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 737 /* alternative array syntax missing intentionally */ 738 ; 739 740 class_name: 741 T_STATIC { $$ = Name[$1]; } 742 | name { $$ = $1; } 743 ; 744 745 name: 746 T_STRING { $$ = Name[$1]; } 747 | T_NAME_QUALIFIED { $$ = Name[$1]; } 748 | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } 749 | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } 750 ; 751 752 class_name_reference: 753 class_name { $$ = $1; } 754 | dynamic_class_name_reference { $$ = $1; } 755 ; 756 757 dynamic_class_name_reference: 758 object_access_for_dcnr { $$ = $1; } 759 | base_variable { $$ = $1; } 760 ; 761 762 class_name_or_var: 763 class_name { $$ = $1; } 764 | reference_variable { $$ = $1; } 765 ; 766 767 object_access_for_dcnr: 768 base_variable T_OBJECT_OPERATOR object_property 769 { $$ = Expr\PropertyFetch[$1, $3]; } 770 | object_access_for_dcnr T_OBJECT_OPERATOR object_property 771 { $$ = Expr\PropertyFetch[$1, $3]; } 772 | object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 773 | object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } 774 ; 775 776 exit_expr: 777 /* empty */ { $$ = null; } 778 | '(' ')' { $$ = null; } 779 | parentheses_expr { $$ = $1; } 780 ; 781 782 backticks_expr: 783 /* empty */ { $$ = array(); } 784 | T_ENCAPSED_AND_WHITESPACE 785 { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); } 786 | encaps_list { parseEncapsed($1, '`', false); $$ = $1; } 787 ; 788 789 ctor_arguments: 790 /* empty */ { $$ = array(); } 791 | argument_list { $$ = $1; } 792 ; 793 794 common_scalar: 795 T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } 796 | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } 797 | T_CONSTANT_ENCAPSED_STRING 798 { $attrs = attributes(); $attrs['kind'] = strKind($1); 799 $$ = new Scalar\String_(Scalar\String_::parse($1, false), $attrs); } 800 | T_LINE { $$ = Scalar\MagicConst\Line[]; } 801 | T_FILE { $$ = Scalar\MagicConst\File[]; } 802 | T_DIR { $$ = Scalar\MagicConst\Dir[]; } 803 | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } 804 | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } 805 | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } 806 | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } 807 | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } 808 | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC 809 { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), false); } 810 | T_START_HEREDOC T_END_HEREDOC 811 { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), false); } 812 ; 813 814 static_scalar: 815 common_scalar { $$ = $1; } 816 | class_name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } 817 | name { $$ = Expr\ConstFetch[$1]; } 818 | T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; } 819 | '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; } 820 | static_operation { $$ = $1; } 821 ; 822 823 static_operation: 824 static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } 825 | static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } 826 | static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } 827 | static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } 828 | static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } 829 | static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } 830 | static_scalar T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG static_scalar 831 { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } 832 | static_scalar T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG static_scalar 833 { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } 834 | static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } 835 | static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; } 836 | static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; } 837 | static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; } 838 | static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; } 839 | static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; } 840 | static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; } 841 | static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } 842 | static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } 843 | static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; } 844 | '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; } 845 | '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; } 846 | '!' static_scalar { $$ = Expr\BooleanNot[$2]; } 847 | '~' static_scalar { $$ = Expr\BitwiseNot[$2]; } 848 | static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; } 849 | static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } 850 | static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; } 851 | static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } 852 | static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; } 853 | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } 854 | static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; } 855 | static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } 856 | static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; } 857 | static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; } 858 | static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 859 | '(' static_scalar ')' { $$ = $2; } 860 ; 861 862 constant: 863 name { $$ = Expr\ConstFetch[$1]; } 864 | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex 865 { $$ = Expr\ClassConstFetch[$1, $3]; } 866 ; 867 868 scalar: 869 common_scalar { $$ = $1; } 870 | constant { $$ = $1; } 871 | '"' encaps_list '"' 872 { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; 873 parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } 874 | T_START_HEREDOC encaps_list T_END_HEREDOC 875 { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } 876 ; 877 878 static_array_pair_list: 879 /* empty */ { $$ = array(); } 880 | non_empty_static_array_pair_list optional_comma { $$ = $1; } 881 ; 882 883 optional_comma: 884 /* empty */ 885 | ',' 886 ; 887 888 non_empty_static_array_pair_list: 889 non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); } 890 | static_array_pair { init($1); } 891 ; 892 893 static_array_pair: 894 static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; } 895 | static_scalar { $$ = Expr\ArrayItem[$1, null, false]; } 896 ; 897 898 variable: 899 object_access { $$ = $1; } 900 | base_variable { $$ = $1; } 901 | function_call { $$ = $1; } 902 | new_expr_array_deref { $$ = $1; } 903 ; 904 905 new_expr_array_deref: 906 '(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; } 907 | new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 908 /* alternative array syntax missing intentionally */ 909 ; 910 911 object_access: 912 variable_or_new_expr T_OBJECT_OPERATOR object_property 913 { $$ = Expr\PropertyFetch[$1, $3]; } 914 | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list 915 { $$ = Expr\MethodCall[$1, $3, $4]; } 916 | object_access argument_list { $$ = Expr\FuncCall[$1, $2]; } 917 | object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 918 | object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } 919 ; 920 921 variable_or_new_expr: 922 variable { $$ = $1; } 923 | '(' new_expr ')' { $$ = $2; } 924 ; 925 926 variable_without_objects: 927 reference_variable { $$ = $1; } 928 | '$' variable_without_objects { $$ = Expr\Variable[$2]; } 929 ; 930 931 base_variable: 932 variable_without_objects { $$ = $1; } 933 | static_property { $$ = $1; } 934 ; 935 936 static_property: 937 class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable 938 { $$ = Expr\StaticPropertyFetch[$1, $4]; } 939 | static_property_with_arrays { $$ = $1; } 940 ; 941 942 static_property_simple_name: 943 T_VARIABLE 944 { $var = parseVar($1); $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } 945 ; 946 947 static_property_with_arrays: 948 class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_property_simple_name 949 { $$ = Expr\StaticPropertyFetch[$1, $3]; } 950 | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}' 951 { $$ = Expr\StaticPropertyFetch[$1, $5]; } 952 | static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 953 | static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } 954 ; 955 956 reference_variable: 957 reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 958 | reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } 959 | plain_variable { $$ = $1; } 960 | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } 961 ; 962 963 dim_offset: 964 /* empty */ { $$ = null; } 965 | expr { $$ = $1; } 966 ; 967 968 object_property: 969 identifier { $$ = $1; } 970 | '{' expr '}' { $$ = $2; } 971 | variable_without_objects { $$ = $1; } 972 | error { $$ = Expr\Error[]; $this->errorState = 2; } 973 ; 974 975 list_expr: 976 T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } 977 ; 978 979 list_expr_elements: 980 list_expr_elements ',' list_expr_element { push($1, $3); } 981 | list_expr_element { init($1); } 982 ; 983 984 list_expr_element: 985 variable { $$ = Expr\ArrayItem[$1, null, false]; } 986 | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } 987 | /* empty */ { $$ = null; } 988 ; 989 990 array_pair_list: 991 /* empty */ { $$ = array(); } 992 | non_empty_array_pair_list optional_comma { $$ = $1; } 993 ; 994 995 non_empty_array_pair_list: 996 non_empty_array_pair_list ',' array_pair { push($1, $3); } 997 | array_pair { init($1); } 998 ; 999 1000 array_pair: 1001 expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } 1002 | expr { $$ = Expr\ArrayItem[$1, null, false]; } 1003 | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } 1004 | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } 1005 | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } 1006 ; 1007 1008 encaps_list: 1009 encaps_list encaps_var { push($1, $2); } 1010 | encaps_list encaps_string_part { push($1, $2); } 1011 | encaps_var { init($1); } 1012 | encaps_string_part encaps_var { init($1, $2); } 1013 ; 1014 1015 encaps_string_part: 1016 T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } 1017 ; 1018 1019 encaps_str_varname: 1020 T_STRING_VARNAME { $$ = Expr\Variable[$1]; } 1021 ; 1022 1023 encaps_var: 1024 plain_variable { $$ = $1; } 1025 | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } 1026 | plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; } 1027 | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } 1028 | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } 1029 | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' 1030 { $$ = Expr\ArrayDimFetch[$2, $4]; } 1031 | T_CURLY_OPEN variable '}' { $$ = $2; } 1032 ; 1033 1034 encaps_var_offset: 1035 T_STRING { $$ = Scalar\String_[$1]; } 1036 | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } 1037 | plain_variable { $$ = $1; } 1038 ; 1039 1040 %% 1041