1 %require "3.0" 2 /* 3 +----------------------------------------------------------------------+ 4 | Zend Engine | 5 +----------------------------------------------------------------------+ 6 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | 7 +----------------------------------------------------------------------+ 8 | This source file is subject to version 2.00 of the Zend license, | 9 | that is bundled with this package in the file LICENSE, and is | 10 | available through the world-wide-web at the following url: | 11 | http://www.zend.com/license/2_00.txt. | 12 | If you did not receive a copy of the Zend license and are unable to | 13 | obtain it through the world-wide-web, please send a note to | 14 | license@zend.com so we can mail you a copy immediately. | 15 +----------------------------------------------------------------------+ 16 | Authors: Andi Gutmans <andi@php.net> | 17 | Zeev Suraski <zeev@php.net> | 18 | Nikita Popov <nikic@php.net> | 19 +----------------------------------------------------------------------+ 20 */ 21 22 %code top { 23 #include "zend.h" 24 #include "zend_list.h" 25 #include "zend_globals.h" 26 #include "zend_API.h" 27 #include "zend_constants.h" 28 #include "zend_language_scanner.h" 29 #include "zend_exceptions.h" 30 31 #define YYSIZE_T size_t 32 #define yytnamerr zend_yytnamerr 33 static YYSIZE_T zend_yytnamerr(char*, const char*); 34 35 #ifdef _MSC_VER 36 #define YYMALLOC malloc 37 #define YYFREE free 38 #endif 39 } 40 41 %code requires { 42 #include "zend_compile.h" 43 } 44 45 %define api.prefix {zend} 46 %define api.pure full 47 %define api.value.type {zend_parser_stack_elem} 48 %define parse.error verbose 49 %expect 0 50 51 %destructor { zend_ast_destroy($$); } <ast> 52 %destructor { if ($$) zend_string_release_ex($$, 0); } <str> 53 54 %precedence T_THROW 55 %precedence PREC_ARROW_FUNCTION 56 %precedence T_INCLUDE T_INCLUDE_ONCE T_REQUIRE T_REQUIRE_ONCE 57 %left T_LOGICAL_OR 58 %left T_LOGICAL_XOR 59 %left T_LOGICAL_AND 60 %precedence T_PRINT 61 %precedence T_YIELD 62 %precedence T_DOUBLE_ARROW 63 %precedence T_YIELD_FROM 64 %precedence '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL 65 %left '?' ':' 66 %right T_COALESCE 67 %left T_BOOLEAN_OR 68 %left T_BOOLEAN_AND 69 %left '|' 70 %left '^' 71 %left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG 72 %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP 73 %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL 74 %left '.' 75 %left T_SL T_SR 76 %left '+' '-' 77 %left '*' '/' '%' 78 %precedence '!' 79 %precedence T_INSTANCEOF 80 %precedence '~' T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' 81 %right T_POW 82 %precedence T_CLONE 83 84 /* Resolve danging else conflict */ 85 %precedence T_NOELSE 86 %precedence T_ELSEIF 87 %precedence T_ELSE 88 89 %token <ast> T_LNUMBER "integer" 90 %token <ast> T_DNUMBER "floating-point number" 91 %token <ast> T_STRING "identifier" 92 %token <ast> T_NAME_FULLY_QUALIFIED "fully qualified name" 93 %token <ast> T_NAME_RELATIVE "namespace-relative name" 94 %token <ast> T_NAME_QUALIFIED "namespaced name" 95 %token <ast> T_VARIABLE "variable" 96 %token <ast> T_INLINE_HTML 97 %token <ast> T_ENCAPSED_AND_WHITESPACE "string content" 98 %token <ast> T_CONSTANT_ENCAPSED_STRING "quoted string" 99 %token <ast> T_STRING_VARNAME "variable name" 100 %token <ast> T_NUM_STRING "number" 101 102 %token <ident> T_INCLUDE "'include'" 103 %token <ident> T_INCLUDE_ONCE "'include_once'" 104 %token <ident> T_EVAL "'eval'" 105 %token <ident> T_REQUIRE "'require'" 106 %token <ident> T_REQUIRE_ONCE "'require_once'" 107 %token <ident> T_LOGICAL_OR "'or'" 108 %token <ident> T_LOGICAL_XOR "'xor'" 109 %token <ident> T_LOGICAL_AND "'and'" 110 %token <ident> T_PRINT "'print'" 111 %token <ident> T_YIELD "'yield'" 112 %token <ident> T_YIELD_FROM "'yield from'" 113 %token <ident> T_INSTANCEOF "'instanceof'" 114 %token <ident> T_NEW "'new'" 115 %token <ident> T_CLONE "'clone'" 116 %token <ident> T_EXIT "'exit'" 117 %token <ident> T_IF "'if'" 118 %token <ident> T_ELSEIF "'elseif'" 119 %token <ident> T_ELSE "'else'" 120 %token <ident> T_ENDIF "'endif'" 121 %token <ident> T_ECHO "'echo'" 122 %token <ident> T_DO "'do'" 123 %token <ident> T_WHILE "'while'" 124 %token <ident> T_ENDWHILE "'endwhile'" 125 %token <ident> T_FOR "'for'" 126 %token <ident> T_ENDFOR "'endfor'" 127 %token <ident> T_FOREACH "'foreach'" 128 %token <ident> T_ENDFOREACH "'endforeach'" 129 %token <ident> T_DECLARE "'declare'" 130 %token <ident> T_ENDDECLARE "'enddeclare'" 131 %token <ident> T_AS "'as'" 132 %token <ident> T_SWITCH "'switch'" 133 %token <ident> T_ENDSWITCH "'endswitch'" 134 %token <ident> T_CASE "'case'" 135 %token <ident> T_DEFAULT "'default'" 136 %token <ident> T_MATCH "'match'" 137 %token <ident> T_BREAK "'break'" 138 %token <ident> T_CONTINUE "'continue'" 139 %token <ident> T_GOTO "'goto'" 140 %token <ident> T_FUNCTION "'function'" 141 %token <ident> T_FN "'fn'" 142 %token <ident> T_CONST "'const'" 143 %token <ident> T_RETURN "'return'" 144 %token <ident> T_TRY "'try'" 145 %token <ident> T_CATCH "'catch'" 146 %token <ident> T_FINALLY "'finally'" 147 %token <ident> T_THROW "'throw'" 148 %token <ident> T_USE "'use'" 149 %token <ident> T_INSTEADOF "'insteadof'" 150 %token <ident> T_GLOBAL "'global'" 151 %token <ident> T_STATIC "'static'" 152 %token <ident> T_ABSTRACT "'abstract'" 153 %token <ident> T_FINAL "'final'" 154 %token <ident> T_PRIVATE "'private'" 155 %token <ident> T_PROTECTED "'protected'" 156 %token <ident> T_PUBLIC "'public'" 157 %token <ident> T_READONLY "'readonly'" 158 %token <ident> T_VAR "'var'" 159 %token <ident> T_UNSET "'unset'" 160 %token <ident> T_ISSET "'isset'" 161 %token <ident> T_EMPTY "'empty'" 162 %token <ident> T_HALT_COMPILER "'__halt_compiler'" 163 %token <ident> T_CLASS "'class'" 164 %token <ident> T_TRAIT "'trait'" 165 %token <ident> T_INTERFACE "'interface'" 166 %token <ident> T_ENUM "'enum'" 167 %token <ident> T_EXTENDS "'extends'" 168 %token <ident> T_IMPLEMENTS "'implements'" 169 %token <ident> T_NAMESPACE "'namespace'" 170 %token <ident> T_LIST "'list'" 171 %token <ident> T_ARRAY "'array'" 172 %token <ident> T_CALLABLE "'callable'" 173 %token <ident> T_LINE "'__LINE__'" 174 %token <ident> T_FILE "'__FILE__'" 175 %token <ident> T_DIR "'__DIR__'" 176 %token <ident> T_CLASS_C "'__CLASS__'" 177 %token <ident> T_TRAIT_C "'__TRAIT__'" 178 %token <ident> T_METHOD_C "'__METHOD__'" 179 %token <ident> T_FUNC_C "'__FUNCTION__'" 180 %token <ident> T_NS_C "'__NAMESPACE__'" 181 182 %token END 0 "end of file" 183 %token T_ATTRIBUTE "'#['" 184 %token T_PLUS_EQUAL "'+='" 185 %token T_MINUS_EQUAL "'-='" 186 %token T_MUL_EQUAL "'*='" 187 %token T_DIV_EQUAL "'/='" 188 %token T_CONCAT_EQUAL "'.='" 189 %token T_MOD_EQUAL "'%='" 190 %token T_AND_EQUAL "'&='" 191 %token T_OR_EQUAL "'|='" 192 %token T_XOR_EQUAL "'^='" 193 %token T_SL_EQUAL "'<<='" 194 %token T_SR_EQUAL "'>>='" 195 %token T_COALESCE_EQUAL "'??='" 196 %token T_BOOLEAN_OR "'||'" 197 %token T_BOOLEAN_AND "'&&'" 198 %token T_IS_EQUAL "'=='" 199 %token T_IS_NOT_EQUAL "'!='" 200 %token T_IS_IDENTICAL "'==='" 201 %token T_IS_NOT_IDENTICAL "'!=='" 202 %token T_IS_SMALLER_OR_EQUAL "'<='" 203 %token T_IS_GREATER_OR_EQUAL "'>='" 204 %token T_SPACESHIP "'<=>'" 205 %token T_SL "'<<'" 206 %token T_SR "'>>'" 207 %token T_INC "'++'" 208 %token T_DEC "'--'" 209 %token T_INT_CAST "'(int)'" 210 %token T_DOUBLE_CAST "'(double)'" 211 %token T_STRING_CAST "'(string)'" 212 %token T_ARRAY_CAST "'(array)'" 213 %token T_OBJECT_CAST "'(object)'" 214 %token T_BOOL_CAST "'(bool)'" 215 %token T_UNSET_CAST "'(unset)'" 216 %token T_OBJECT_OPERATOR "'->'" 217 %token T_NULLSAFE_OBJECT_OPERATOR "'?->'" 218 %token T_DOUBLE_ARROW "'=>'" 219 %token T_COMMENT "comment" 220 %token T_DOC_COMMENT "doc comment" 221 %token T_OPEN_TAG "open tag" 222 %token T_OPEN_TAG_WITH_ECHO "'<?='" 223 %token T_CLOSE_TAG "'?>'" 224 %token T_WHITESPACE "whitespace" 225 %token T_START_HEREDOC "heredoc start" 226 %token T_END_HEREDOC "heredoc end" 227 %token T_DOLLAR_OPEN_CURLY_BRACES "'${'" 228 %token T_CURLY_OPEN "'{$'" 229 %token T_PAAMAYIM_NEKUDOTAYIM "'::'" 230 %token T_NS_SEPARATOR "'\\'" 231 %token T_ELLIPSIS "'...'" 232 %token T_COALESCE "'??'" 233 %token T_POW "'**'" 234 %token T_POW_EQUAL "'**='" 235 /* We need to split the & token in two to avoid a shift/reduce conflict. For T1&$v and T1&T2, 236 * with only one token lookahead, bison does not know whether to reduce T1 as a complete type, 237 * or shift to continue parsing an intersection type. */ 238 %token T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG "'&'" 239 /* Bison warns on duplicate token literals, so use a different dummy value here. 240 * It will be fixed up by zend_yytnamerr() later. */ 241 %token T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG "amp" 242 %token T_BAD_CHARACTER "invalid character" 243 244 /* Token used to force a parse error from the lexer */ 245 %token T_ERROR 246 247 %type <ast> top_statement namespace_name name statement function_declaration_statement 248 %type <ast> class_declaration_statement trait_declaration_statement legacy_namespace_name 249 %type <ast> interface_declaration_statement interface_extends_list 250 %type <ast> group_use_declaration inline_use_declarations inline_use_declaration 251 %type <ast> mixed_group_use_declaration use_declaration unprefixed_use_declaration 252 %type <ast> unprefixed_use_declarations const_decl inner_statement 253 %type <ast> expr optional_expr while_statement for_statement foreach_variable 254 %type <ast> foreach_statement declare_statement finally_statement unset_variable variable 255 %type <ast> extends_from parameter optional_type_without_static argument global_var 256 %type <ast> static_var class_statement trait_adaptation trait_precedence trait_alias 257 %type <ast> absolute_trait_method_reference trait_method_reference property echo_expr 258 %type <ast> new_expr anonymous_class class_name class_name_reference simple_variable 259 %type <ast> internal_functions_in_yacc 260 %type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name property_name 261 %type <ast> variable_class_name dereferenceable_scalar constant class_constant 262 %type <ast> fully_dereferenceable array_object_dereferenceable 263 %type <ast> callable_expr callable_variable static_member new_variable 264 %type <ast> encaps_var encaps_var_offset isset_variables 265 %type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt 266 %type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list 267 %type <ast> echo_expr_list unset_variables catch_name_list catch_list optional_variable parameter_list class_statement_list 268 %type <ast> implements_list case_list if_stmt_without_else 269 %type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list 270 %type <ast> class_const_list class_const_decl class_name_list trait_adaptations method_body non_empty_for_exprs 271 %type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars 272 %type <ast> lexical_var_list encaps_list 273 %type <ast> array_pair non_empty_array_pair_list array_pair_list possible_array_pair 274 %type <ast> isset_variable type return_type type_expr type_without_static 275 %type <ast> identifier type_expr_without_static union_type_without_static_element union_type_without_static intersection_type_without_static 276 %type <ast> inline_function union_type_element union_type intersection_type 277 %type <ast> attributed_statement attributed_class_statement attributed_parameter 278 %type <ast> attribute_decl attribute attributes attribute_group namespace_declaration_name 279 %type <ast> match match_arm_list non_empty_match_arm_list match_arm match_arm_cond_list 280 %type <ast> enum_declaration_statement enum_backing_type enum_case enum_case_expr 281 %type <ast> function_name 282 283 %type <num> returns_ref function fn is_reference is_variadic variable_modifiers 284 %type <num> method_modifiers non_empty_member_modifiers member_modifier 285 %type <num> optional_property_modifiers property_modifier 286 %type <num> class_modifiers class_modifier use_type backup_fn_flags 287 288 %type <ptr> backup_lex_pos 289 %type <str> backup_doc_comment 290 291 %type <ident> reserved_non_modifiers semi_reserved 292 293 %% /* Rules */ 294 295 start: 296 top_statement_list { CG(ast) = $1; (void) zendnerrs; } 297 ; 298 299 reserved_non_modifiers: 300 T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND 301 | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE | T_ENDWHILE 302 | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH | T_FINALLY 303 | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO 304 | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK 305 | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS 306 | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_FN | T_MATCH | T_ENUM 307 ; 308 309 semi_reserved: 310 reserved_non_modifiers 311 | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC | T_READONLY 312 ; 313 314 ampersand: 315 T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG 316 | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG 317 ; 318 319 identifier: 320 T_STRING { $$ = $1; } 321 | semi_reserved { 322 zval zv; 323 if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } 324 $$ = zend_ast_create_zval(&zv); 325 } 326 ; 327 328 top_statement_list: 329 top_statement_list top_statement { $$ = zend_ast_list_add($1, $2); } 330 | %empty { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); } 331 ; 332 333 /* Name usable in a namespace declaration. */ 334 namespace_declaration_name: 335 identifier { $$ = $1; } 336 | T_NAME_QUALIFIED { $$ = $1; } 337 ; 338 339 /* Name usable in "use" declarations (leading separator forbidden). */ 340 namespace_name: 341 T_STRING { $$ = $1; } 342 | T_NAME_QUALIFIED { $$ = $1; } 343 ; 344 345 /* Name usable in "use" declarations (leading separator allowed). */ 346 legacy_namespace_name: 347 namespace_name { $$ = $1; } 348 | T_NAME_FULLY_QUALIFIED { $$ = $1; } 349 ; 350 351 name: 352 T_STRING { $$ = $1; $$->attr = ZEND_NAME_NOT_FQ; } 353 | T_NAME_QUALIFIED { $$ = $1; $$->attr = ZEND_NAME_NOT_FQ; } 354 | T_NAME_FULLY_QUALIFIED { $$ = $1; $$->attr = ZEND_NAME_FQ; } 355 | T_NAME_RELATIVE { $$ = $1; $$->attr = ZEND_NAME_RELATIVE; } 356 ; 357 358 attribute_decl: 359 class_name 360 { $$ = zend_ast_create(ZEND_AST_ATTRIBUTE, $1, NULL); } 361 | class_name argument_list 362 { $$ = zend_ast_create(ZEND_AST_ATTRIBUTE, $1, $2); } 363 ; 364 365 attribute_group: 366 attribute_decl 367 { $$ = zend_ast_create_list(1, ZEND_AST_ATTRIBUTE_GROUP, $1); } 368 | attribute_group ',' attribute_decl 369 { $$ = zend_ast_list_add($1, $3); } 370 ; 371 372 attribute: 373 T_ATTRIBUTE attribute_group possible_comma ']' { $$ = $2; } 374 ; 375 376 attributes: 377 attribute { $$ = zend_ast_create_list(1, ZEND_AST_ATTRIBUTE_LIST, $1); } 378 | attributes attribute { $$ = zend_ast_list_add($1, $2); } 379 ; 380 381 attributed_statement: 382 function_declaration_statement { $$ = $1; } 383 | class_declaration_statement { $$ = $1; } 384 | trait_declaration_statement { $$ = $1; } 385 | interface_declaration_statement { $$ = $1; } 386 | enum_declaration_statement { $$ = $1; } 387 ; 388 389 top_statement: 390 statement { $$ = $1; } 391 | attributed_statement { $$ = $1; } 392 | attributes attributed_statement { $$ = zend_ast_with_attributes($2, $1); } 393 | T_HALT_COMPILER '(' ')' ';' 394 { $$ = zend_ast_create(ZEND_AST_HALT_COMPILER, 395 zend_ast_create_zval_from_long(zend_get_scanned_file_offset())); 396 zend_stop_lexing(); } 397 | T_NAMESPACE namespace_declaration_name ';' 398 { $$ = zend_ast_create(ZEND_AST_NAMESPACE, $2, NULL); 399 RESET_DOC_COMMENT(); } 400 | T_NAMESPACE namespace_declaration_name { RESET_DOC_COMMENT(); } 401 '{' top_statement_list '}' 402 { $$ = zend_ast_create(ZEND_AST_NAMESPACE, $2, $5); } 403 | T_NAMESPACE { RESET_DOC_COMMENT(); } 404 '{' top_statement_list '}' 405 { $$ = zend_ast_create(ZEND_AST_NAMESPACE, NULL, $4); } 406 | T_USE mixed_group_use_declaration ';' { $$ = $2; } 407 | T_USE use_type group_use_declaration ';' { $$ = $3; $$->attr = $2; } 408 | T_USE use_declarations ';' { $$ = $2; $$->attr = ZEND_SYMBOL_CLASS; } 409 | T_USE use_type use_declarations ';' { $$ = $3; $$->attr = $2; } 410 | T_CONST const_list ';' { $$ = $2; } 411 ; 412 413 use_type: 414 T_FUNCTION { $$ = ZEND_SYMBOL_FUNCTION; } 415 | T_CONST { $$ = ZEND_SYMBOL_CONST; } 416 ; 417 418 group_use_declaration: 419 legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations possible_comma '}' 420 { $$ = zend_ast_create(ZEND_AST_GROUP_USE, $1, $4); } 421 ; 422 423 mixed_group_use_declaration: 424 legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations possible_comma '}' 425 { $$ = zend_ast_create(ZEND_AST_GROUP_USE, $1, $4);} 426 ; 427 428 possible_comma: 429 %empty 430 | ',' 431 ; 432 433 inline_use_declarations: 434 inline_use_declarations ',' inline_use_declaration 435 { $$ = zend_ast_list_add($1, $3); } 436 | inline_use_declaration 437 { $$ = zend_ast_create_list(1, ZEND_AST_USE, $1); } 438 ; 439 440 unprefixed_use_declarations: 441 unprefixed_use_declarations ',' unprefixed_use_declaration 442 { $$ = zend_ast_list_add($1, $3); } 443 | unprefixed_use_declaration 444 { $$ = zend_ast_create_list(1, ZEND_AST_USE, $1); } 445 ; 446 447 use_declarations: 448 use_declarations ',' use_declaration 449 { $$ = zend_ast_list_add($1, $3); } 450 | use_declaration 451 { $$ = zend_ast_create_list(1, ZEND_AST_USE, $1); } 452 ; 453 454 inline_use_declaration: 455 unprefixed_use_declaration { $$ = $1; $$->attr = ZEND_SYMBOL_CLASS; } 456 | use_type unprefixed_use_declaration { $$ = $2; $$->attr = $1; } 457 ; 458 459 unprefixed_use_declaration: 460 namespace_name 461 { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, NULL); } 462 | namespace_name T_AS T_STRING 463 { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, $3); } 464 ; 465 466 use_declaration: 467 legacy_namespace_name 468 { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, NULL); } 469 | legacy_namespace_name T_AS T_STRING 470 { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, $3); } 471 ; 472 473 const_list: 474 const_list ',' const_decl { $$ = zend_ast_list_add($1, $3); } 475 | const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CONST_DECL, $1); } 476 ; 477 478 inner_statement_list: 479 inner_statement_list inner_statement 480 { $$ = zend_ast_list_add($1, $2); } 481 | %empty 482 { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); } 483 ; 484 485 486 inner_statement: 487 statement { $$ = $1; } 488 | attributed_statement { $$ = $1; } 489 | attributes attributed_statement { $$ = zend_ast_with_attributes($2, $1); } 490 | T_HALT_COMPILER '(' ')' ';' 491 { $$ = NULL; zend_throw_exception(zend_ce_compile_error, 492 "__HALT_COMPILER() can only be used from the outermost scope", 0); YYERROR; } 493 ; 494 495 496 statement: 497 '{' inner_statement_list '}' { $$ = $2; } 498 | if_stmt { $$ = $1; } 499 | alt_if_stmt { $$ = $1; } 500 | T_WHILE '(' expr ')' while_statement 501 { $$ = zend_ast_create(ZEND_AST_WHILE, $3, $5); } 502 | T_DO statement T_WHILE '(' expr ')' ';' 503 { $$ = zend_ast_create(ZEND_AST_DO_WHILE, $2, $5); } 504 | T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement 505 { $$ = zend_ast_create(ZEND_AST_FOR, $3, $5, $7, $9); } 506 | T_SWITCH '(' expr ')' switch_case_list 507 { $$ = zend_ast_create(ZEND_AST_SWITCH, $3, $5); } 508 | T_BREAK optional_expr ';' { $$ = zend_ast_create(ZEND_AST_BREAK, $2); } 509 | T_CONTINUE optional_expr ';' { $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); } 510 | T_RETURN optional_expr ';' { $$ = zend_ast_create(ZEND_AST_RETURN, $2); } 511 | T_GLOBAL global_var_list ';' { $$ = $2; } 512 | T_STATIC static_var_list ';' { $$ = $2; } 513 | T_ECHO echo_expr_list ';' { $$ = $2; } 514 | T_INLINE_HTML { $$ = zend_ast_create(ZEND_AST_ECHO, $1); } 515 | expr ';' { $$ = $1; } 516 | T_UNSET '(' unset_variables possible_comma ')' ';' { $$ = $3; } 517 | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement 518 { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $5, NULL, $7); } 519 | T_FOREACH '(' expr T_AS foreach_variable T_DOUBLE_ARROW foreach_variable ')' 520 foreach_statement 521 { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $7, $5, $9); } 522 | T_DECLARE '(' const_list ')' 523 { if (!zend_handle_encoding_declaration($3)) { YYERROR; } } 524 declare_statement 525 { $$ = zend_ast_create(ZEND_AST_DECLARE, $3, $6); } 526 | ';' /* empty statement */ { $$ = NULL; } 527 | T_TRY '{' inner_statement_list '}' catch_list finally_statement 528 { $$ = zend_ast_create(ZEND_AST_TRY, $3, $5, $6); } 529 | T_GOTO T_STRING ';' { $$ = zend_ast_create(ZEND_AST_GOTO, $2); } 530 | T_STRING ':' { $$ = zend_ast_create(ZEND_AST_LABEL, $1); } 531 ; 532 533 catch_list: 534 %empty 535 { $$ = zend_ast_create_list(0, ZEND_AST_CATCH_LIST); } 536 | catch_list T_CATCH '(' catch_name_list optional_variable ')' '{' inner_statement_list '}' 537 { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_CATCH, $4, $5, $8)); } 538 ; 539 540 catch_name_list: 541 class_name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); } 542 | catch_name_list '|' class_name { $$ = zend_ast_list_add($1, $3); } 543 ; 544 545 optional_variable: 546 %empty { $$ = NULL; } 547 | T_VARIABLE { $$ = $1; } 548 ; 549 550 finally_statement: 551 %empty { $$ = NULL; } 552 | T_FINALLY '{' inner_statement_list '}' { $$ = $3; } 553 ; 554 555 unset_variables: 556 unset_variable { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } 557 | unset_variables ',' unset_variable { $$ = zend_ast_list_add($1, $3); } 558 ; 559 560 unset_variable: 561 variable { $$ = zend_ast_create(ZEND_AST_UNSET, $1); } 562 ; 563 564 function_name: 565 T_STRING { $$ = $1; } 566 | T_READONLY { 567 zval zv; 568 if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } 569 $$ = zend_ast_create_zval(&zv); 570 } 571 ; 572 573 function_declaration_statement: 574 function returns_ref function_name backup_doc_comment '(' parameter_list ')' return_type 575 backup_fn_flags '{' inner_statement_list '}' backup_fn_flags 576 { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2 | $13, $1, $4, 577 zend_ast_get_str($3), $6, NULL, $11, $8, NULL); CG(extra_fn_flags) = $9; } 578 ; 579 580 is_reference: 581 %empty { $$ = 0; } 582 | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = ZEND_PARAM_REF; } 583 ; 584 585 is_variadic: 586 %empty { $$ = 0; } 587 | T_ELLIPSIS { $$ = ZEND_PARAM_VARIADIC; } 588 ; 589 590 class_declaration_statement: 591 class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); } 592 T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' 593 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>3, $7, zend_ast_get_str($4), $5, $6, $9, NULL, NULL); } 594 | T_CLASS { $<num>$ = CG(zend_lineno); } 595 T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' 596 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>2, $6, zend_ast_get_str($3), $4, $5, $8, NULL, NULL); } 597 ; 598 599 class_modifiers: 600 class_modifier { $$ = $1; } 601 | class_modifiers class_modifier 602 { $$ = zend_add_class_modifier($1, $2); if (!$$) { YYERROR; } } 603 ; 604 605 class_modifier: 606 T_ABSTRACT { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } 607 | T_FINAL { $$ = ZEND_ACC_FINAL; } 608 | T_READONLY { $$ = ZEND_ACC_READONLY_CLASS|ZEND_ACC_NO_DYNAMIC_PROPERTIES; } 609 ; 610 611 trait_declaration_statement: 612 T_TRAIT { $<num>$ = CG(zend_lineno); } 613 T_STRING backup_doc_comment '{' class_statement_list '}' 614 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $<num>2, $4, zend_ast_get_str($3), NULL, NULL, $6, NULL, NULL); } 615 ; 616 617 interface_declaration_statement: 618 T_INTERFACE { $<num>$ = CG(zend_lineno); } 619 T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}' 620 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5, zend_ast_get_str($3), NULL, $4, $7, NULL, NULL); } 621 ; 622 623 enum_declaration_statement: 624 T_ENUM { $<num>$ = CG(zend_lineno); } 625 T_STRING enum_backing_type implements_list backup_doc_comment '{' class_statement_list '}' 626 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_ENUM|ZEND_ACC_FINAL, $<num>2, $6, zend_ast_get_str($3), NULL, $5, $8, NULL, $4); } 627 ; 628 629 enum_backing_type: 630 %empty { $$ = NULL; } 631 | ':' type_expr { $$ = $2; } 632 ; 633 634 enum_case: 635 T_CASE backup_doc_comment identifier enum_case_expr ';' 636 { $$ = zend_ast_create(ZEND_AST_ENUM_CASE, $3, $4, ($2 ? zend_ast_create_zval_from_str($2) : NULL), NULL); } 637 ; 638 639 enum_case_expr: 640 %empty { $$ = NULL; } 641 | '=' expr { $$ = $2; } 642 ; 643 644 extends_from: 645 %empty { $$ = NULL; } 646 | T_EXTENDS class_name { $$ = $2; } 647 ; 648 649 interface_extends_list: 650 %empty { $$ = NULL; } 651 | T_EXTENDS class_name_list { $$ = $2; } 652 ; 653 654 implements_list: 655 %empty { $$ = NULL; } 656 | T_IMPLEMENTS class_name_list { $$ = $2; } 657 ; 658 659 foreach_variable: 660 variable { $$ = $1; } 661 | ampersand variable { $$ = zend_ast_create(ZEND_AST_REF, $2); } 662 | T_LIST '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LIST; } 663 | '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; } 664 ; 665 666 for_statement: 667 statement { $$ = $1; } 668 | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } 669 ; 670 671 foreach_statement: 672 statement { $$ = $1; } 673 | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } 674 ; 675 676 declare_statement: 677 statement { $$ = $1; } 678 | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } 679 ; 680 681 switch_case_list: 682 '{' case_list '}' { $$ = $2; } 683 | '{' ';' case_list '}' { $$ = $3; } 684 | ':' case_list T_ENDSWITCH ';' { $$ = $2; } 685 | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } 686 ; 687 688 case_list: 689 %empty { $$ = zend_ast_create_list(0, ZEND_AST_SWITCH_LIST); } 690 | case_list T_CASE expr case_separator inner_statement_list 691 { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, $3, $5)); } 692 | case_list T_DEFAULT case_separator inner_statement_list 693 { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, NULL, $4)); } 694 ; 695 696 case_separator: 697 ':' 698 | ';' 699 ; 700 701 702 match: 703 T_MATCH '(' expr ')' '{' match_arm_list '}' 704 { $$ = zend_ast_create(ZEND_AST_MATCH, $3, $6); }; 705 ; 706 707 match_arm_list: 708 %empty { $$ = zend_ast_create_list(0, ZEND_AST_MATCH_ARM_LIST); } 709 | non_empty_match_arm_list possible_comma { $$ = $1; } 710 ; 711 712 non_empty_match_arm_list: 713 match_arm { $$ = zend_ast_create_list(1, ZEND_AST_MATCH_ARM_LIST, $1); } 714 | non_empty_match_arm_list ',' match_arm { $$ = zend_ast_list_add($1, $3); } 715 ; 716 717 match_arm: 718 match_arm_cond_list possible_comma T_DOUBLE_ARROW expr 719 { $$ = zend_ast_create(ZEND_AST_MATCH_ARM, $1, $4); } 720 | T_DEFAULT possible_comma T_DOUBLE_ARROW expr 721 { $$ = zend_ast_create(ZEND_AST_MATCH_ARM, NULL, $4); } 722 ; 723 724 match_arm_cond_list: 725 expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } 726 | match_arm_cond_list ',' expr { $$ = zend_ast_list_add($1, $3); } 727 ; 728 729 730 while_statement: 731 statement { $$ = $1; } 732 | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } 733 ; 734 735 736 if_stmt_without_else: 737 T_IF '(' expr ')' statement 738 { $$ = zend_ast_create_list(1, ZEND_AST_IF, 739 zend_ast_create(ZEND_AST_IF_ELEM, $3, $5)); } 740 | if_stmt_without_else T_ELSEIF '(' expr ')' statement 741 { $$ = zend_ast_list_add($1, 742 zend_ast_create(ZEND_AST_IF_ELEM, $4, $6)); } 743 ; 744 745 if_stmt: 746 if_stmt_without_else %prec T_NOELSE { $$ = $1; } 747 | if_stmt_without_else T_ELSE statement 748 { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_IF_ELEM, NULL, $3)); } 749 ; 750 751 alt_if_stmt_without_else: 752 T_IF '(' expr ')' ':' inner_statement_list 753 { $$ = zend_ast_create_list(1, ZEND_AST_IF, 754 zend_ast_create(ZEND_AST_IF_ELEM, $3, $6)); } 755 | alt_if_stmt_without_else T_ELSEIF '(' expr ')' ':' inner_statement_list 756 { $$ = zend_ast_list_add($1, 757 zend_ast_create(ZEND_AST_IF_ELEM, $4, $7)); } 758 ; 759 760 alt_if_stmt: 761 alt_if_stmt_without_else T_ENDIF ';' { $$ = $1; } 762 | alt_if_stmt_without_else T_ELSE ':' inner_statement_list T_ENDIF ';' 763 { $$ = zend_ast_list_add($1, 764 zend_ast_create(ZEND_AST_IF_ELEM, NULL, $4)); } 765 ; 766 767 parameter_list: 768 non_empty_parameter_list possible_comma { $$ = $1; } 769 | %empty { $$ = zend_ast_create_list(0, ZEND_AST_PARAM_LIST); } 770 ; 771 772 773 non_empty_parameter_list: 774 attributed_parameter 775 { $$ = zend_ast_create_list(1, ZEND_AST_PARAM_LIST, $1); } 776 | non_empty_parameter_list ',' attributed_parameter 777 { $$ = zend_ast_list_add($1, $3); } 778 ; 779 780 attributed_parameter: 781 attributes parameter { $$ = zend_ast_with_attributes($2, $1); } 782 | parameter { $$ = $1; } 783 ; 784 785 optional_property_modifiers: 786 %empty { $$ = 0; } 787 | optional_property_modifiers property_modifier 788 { $$ = zend_add_member_modifier($1, $2); if (!$$) { YYERROR; } } 789 790 property_modifier: 791 T_PUBLIC { $$ = ZEND_ACC_PUBLIC; } 792 | T_PROTECTED { $$ = ZEND_ACC_PROTECTED; } 793 | T_PRIVATE { $$ = ZEND_ACC_PRIVATE; } 794 | T_READONLY { $$ = ZEND_ACC_READONLY; } 795 ; 796 797 parameter: 798 optional_property_modifiers optional_type_without_static 799 is_reference is_variadic T_VARIABLE backup_doc_comment 800 { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $1 | $3 | $4, $2, $5, NULL, 801 NULL, $6 ? zend_ast_create_zval_from_str($6) : NULL); } 802 | optional_property_modifiers optional_type_without_static 803 is_reference is_variadic T_VARIABLE backup_doc_comment '=' expr 804 { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $1 | $3 | $4, $2, $5, $8, 805 NULL, $6 ? zend_ast_create_zval_from_str($6) : NULL); } 806 ; 807 808 809 optional_type_without_static: 810 %empty { $$ = NULL; } 811 | type_expr_without_static { $$ = $1; } 812 ; 813 814 type_expr: 815 type { $$ = $1; } 816 | '?' type { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; } 817 | union_type { $$ = $1; } 818 | intersection_type { $$ = $1; } 819 ; 820 821 type: 822 type_without_static { $$ = $1; } 823 | T_STATIC { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_STATIC); } 824 ; 825 826 union_type_element: 827 type { $$ = $1; } 828 | '(' intersection_type ')' { $$ = $2; } 829 ; 830 831 union_type: 832 union_type_element '|' union_type_element 833 { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } 834 | union_type '|' union_type_element 835 { $$ = zend_ast_list_add($1, $3); } 836 ; 837 838 intersection_type: 839 type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_INTERSECTION, $1, $3); } 840 | intersection_type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { $$ = zend_ast_list_add($1, $3); } 841 ; 842 843 /* Duplicate the type rules without "static", 844 * to avoid conflicts with "static" modifier for properties. */ 845 846 type_expr_without_static: 847 type_without_static { $$ = $1; } 848 | '?' type_without_static { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; } 849 | union_type_without_static { $$ = $1; } 850 | intersection_type_without_static { $$ = $1; } 851 ; 852 853 type_without_static: 854 T_ARRAY { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); } 855 | T_CALLABLE { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_CALLABLE); } 856 | name { $$ = $1; } 857 ; 858 859 union_type_without_static_element: 860 type_without_static { $$ = $1; } 861 | '(' intersection_type_without_static ')' { $$ = $2; } 862 ; 863 864 union_type_without_static: 865 union_type_without_static_element '|' union_type_without_static_element 866 { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } 867 | union_type_without_static '|' union_type_without_static_element 868 { $$ = zend_ast_list_add($1, $3); } 869 ; 870 871 intersection_type_without_static: 872 type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static 873 { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_INTERSECTION, $1, $3); } 874 | intersection_type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static 875 { $$ = zend_ast_list_add($1, $3); } 876 ; 877 878 return_type: 879 %empty { $$ = NULL; } 880 | ':' type_expr { $$ = $2; } 881 ; 882 883 argument_list: 884 '(' ')' { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); } 885 | '(' non_empty_argument_list possible_comma ')' { $$ = $2; } 886 | '(' T_ELLIPSIS ')' { $$ = zend_ast_create(ZEND_AST_CALLABLE_CONVERT); } 887 ; 888 889 non_empty_argument_list: 890 argument 891 { $$ = zend_ast_create_list(1, ZEND_AST_ARG_LIST, $1); } 892 | non_empty_argument_list ',' argument 893 { $$ = zend_ast_list_add($1, $3); } 894 ; 895 896 argument: 897 expr { $$ = $1; } 898 | identifier ':' expr 899 { $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, $3); } 900 | T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); } 901 ; 902 903 global_var_list: 904 global_var_list ',' global_var { $$ = zend_ast_list_add($1, $3); } 905 | global_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } 906 ; 907 908 global_var: 909 simple_variable 910 { $$ = zend_ast_create(ZEND_AST_GLOBAL, zend_ast_create(ZEND_AST_VAR, $1)); } 911 ; 912 913 914 static_var_list: 915 static_var_list ',' static_var { $$ = zend_ast_list_add($1, $3); } 916 | static_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } 917 ; 918 919 static_var: 920 T_VARIABLE { $$ = zend_ast_create(ZEND_AST_STATIC, $1, NULL); } 921 | T_VARIABLE '=' expr { $$ = zend_ast_create(ZEND_AST_STATIC, $1, $3); } 922 ; 923 924 class_statement_list: 925 class_statement_list class_statement 926 { $$ = zend_ast_list_add($1, $2); } 927 | %empty 928 { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); } 929 ; 930 931 932 attributed_class_statement: 933 variable_modifiers optional_type_without_static property_list ';' 934 { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3, NULL); 935 $$->attr = $1; } 936 | method_modifiers T_CONST class_const_list ';' 937 { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL); 938 $$->attr = $1; } 939 | method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')' 940 return_type backup_fn_flags method_body backup_fn_flags 941 { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1 | $12, $2, $5, 942 zend_ast_get_str($4), $7, NULL, $11, $9, NULL); CG(extra_fn_flags) = $10; } 943 | enum_case { $$ = $1; } 944 ; 945 946 class_statement: 947 attributed_class_statement { $$ = $1; } 948 | attributes attributed_class_statement { $$ = zend_ast_with_attributes($2, $1); } 949 | T_USE class_name_list trait_adaptations 950 { $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); } 951 ; 952 953 class_name_list: 954 class_name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); } 955 | class_name_list ',' class_name { $$ = zend_ast_list_add($1, $3); } 956 ; 957 958 trait_adaptations: 959 ';' { $$ = NULL; } 960 | '{' '}' { $$ = NULL; } 961 | '{' trait_adaptation_list '}' { $$ = $2; } 962 ; 963 964 trait_adaptation_list: 965 trait_adaptation 966 { $$ = zend_ast_create_list(1, ZEND_AST_TRAIT_ADAPTATIONS, $1); } 967 | trait_adaptation_list trait_adaptation 968 { $$ = zend_ast_list_add($1, $2); } 969 ; 970 971 trait_adaptation: 972 trait_precedence ';' { $$ = $1; } 973 | trait_alias ';' { $$ = $1; } 974 ; 975 976 trait_precedence: 977 absolute_trait_method_reference T_INSTEADOF class_name_list 978 { $$ = zend_ast_create(ZEND_AST_TRAIT_PRECEDENCE, $1, $3); } 979 ; 980 981 trait_alias: 982 trait_method_reference T_AS T_STRING 983 { $$ = zend_ast_create(ZEND_AST_TRAIT_ALIAS, $1, $3); } 984 | trait_method_reference T_AS reserved_non_modifiers 985 { zval zv; 986 if (zend_lex_tstring(&zv, $3) == FAILURE) { YYABORT; } 987 $$ = zend_ast_create(ZEND_AST_TRAIT_ALIAS, $1, zend_ast_create_zval(&zv)); } 988 | trait_method_reference T_AS member_modifier identifier 989 { $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, $4); } 990 | trait_method_reference T_AS member_modifier 991 { $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, NULL); } 992 ; 993 994 trait_method_reference: 995 identifier 996 { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, NULL, $1); } 997 | absolute_trait_method_reference { $$ = $1; } 998 ; 999 1000 absolute_trait_method_reference: 1001 class_name T_PAAMAYIM_NEKUDOTAYIM identifier 1002 { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, $1, $3); } 1003 ; 1004 1005 method_body: 1006 ';' /* abstract method */ { $$ = NULL; } 1007 | '{' inner_statement_list '}' { $$ = $2; } 1008 ; 1009 1010 variable_modifiers: 1011 non_empty_member_modifiers { $$ = $1; } 1012 | T_VAR { $$ = ZEND_ACC_PUBLIC; } 1013 ; 1014 1015 method_modifiers: 1016 %empty { $$ = ZEND_ACC_PUBLIC; } 1017 | non_empty_member_modifiers 1018 { $$ = $1; if (!($$ & ZEND_ACC_PPP_MASK)) { $$ |= ZEND_ACC_PUBLIC; } } 1019 ; 1020 1021 non_empty_member_modifiers: 1022 member_modifier { $$ = $1; } 1023 | non_empty_member_modifiers member_modifier 1024 { $$ = zend_add_member_modifier($1, $2); if (!$$) { YYERROR; } } 1025 ; 1026 1027 member_modifier: 1028 T_PUBLIC { $$ = ZEND_ACC_PUBLIC; } 1029 | T_PROTECTED { $$ = ZEND_ACC_PROTECTED; } 1030 | T_PRIVATE { $$ = ZEND_ACC_PRIVATE; } 1031 | T_STATIC { $$ = ZEND_ACC_STATIC; } 1032 | T_ABSTRACT { $$ = ZEND_ACC_ABSTRACT; } 1033 | T_FINAL { $$ = ZEND_ACC_FINAL; } 1034 | T_READONLY { $$ = ZEND_ACC_READONLY; } 1035 ; 1036 1037 property_list: 1038 property_list ',' property { $$ = zend_ast_list_add($1, $3); } 1039 | property { $$ = zend_ast_create_list(1, ZEND_AST_PROP_DECL, $1); } 1040 ; 1041 1042 property: 1043 T_VARIABLE backup_doc_comment 1044 { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, NULL, ($2 ? zend_ast_create_zval_from_str($2) : NULL)); } 1045 | T_VARIABLE '=' expr backup_doc_comment 1046 { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } 1047 ; 1048 1049 class_const_list: 1050 class_const_list ',' class_const_decl { $$ = zend_ast_list_add($1, $3); } 1051 | class_const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); } 1052 ; 1053 1054 class_const_decl: 1055 identifier '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } 1056 ; 1057 1058 const_decl: 1059 T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } 1060 ; 1061 1062 echo_expr_list: 1063 echo_expr_list ',' echo_expr { $$ = zend_ast_list_add($1, $3); } 1064 | echo_expr { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } 1065 ; 1066 echo_expr: 1067 expr { $$ = zend_ast_create(ZEND_AST_ECHO, $1); } 1068 ; 1069 1070 for_exprs: 1071 %empty { $$ = NULL; } 1072 | non_empty_for_exprs { $$ = $1; } 1073 ; 1074 1075 non_empty_for_exprs: 1076 non_empty_for_exprs ',' expr { $$ = zend_ast_list_add($1, $3); } 1077 | expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } 1078 ; 1079 1080 anonymous_class: 1081 T_CLASS { $<num>$ = CG(zend_lineno); } ctor_arguments 1082 extends_from implements_list backup_doc_comment '{' class_statement_list '}' { 1083 zend_ast *decl = zend_ast_create_decl( 1084 ZEND_AST_CLASS, ZEND_ACC_ANON_CLASS, $<num>2, $6, NULL, 1085 $4, $5, $8, NULL, NULL); 1086 $$ = zend_ast_create(ZEND_AST_NEW, decl, $3); 1087 } 1088 ; 1089 1090 new_expr: 1091 T_NEW class_name_reference ctor_arguments 1092 { $$ = zend_ast_create(ZEND_AST_NEW, $2, $3); } 1093 | T_NEW anonymous_class 1094 { $$ = $2; } 1095 | T_NEW attributes anonymous_class 1096 { zend_ast_with_attributes($3->child[0], $2); $$ = $3; } 1097 ; 1098 1099 expr: 1100 variable 1101 { $$ = $1; } 1102 | T_LIST '(' array_pair_list ')' '=' expr 1103 { $3->attr = ZEND_ARRAY_SYNTAX_LIST; $$ = zend_ast_create(ZEND_AST_ASSIGN, $3, $6); } 1104 | '[' array_pair_list ']' '=' expr 1105 { $2->attr = ZEND_ARRAY_SYNTAX_SHORT; $$ = zend_ast_create(ZEND_AST_ASSIGN, $2, $5); } 1106 | variable '=' expr 1107 { $$ = zend_ast_create(ZEND_AST_ASSIGN, $1, $3); } 1108 | variable '=' ampersand variable 1109 { $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); } 1110 | T_CLONE expr { $$ = zend_ast_create(ZEND_AST_CLONE, $2); } 1111 | variable T_PLUS_EQUAL expr 1112 { $$ = zend_ast_create_assign_op(ZEND_ADD, $1, $3); } 1113 | variable T_MINUS_EQUAL expr 1114 { $$ = zend_ast_create_assign_op(ZEND_SUB, $1, $3); } 1115 | variable T_MUL_EQUAL expr 1116 { $$ = zend_ast_create_assign_op(ZEND_MUL, $1, $3); } 1117 | variable T_POW_EQUAL expr 1118 { $$ = zend_ast_create_assign_op(ZEND_POW, $1, $3); } 1119 | variable T_DIV_EQUAL expr 1120 { $$ = zend_ast_create_assign_op(ZEND_DIV, $1, $3); } 1121 | variable T_CONCAT_EQUAL expr 1122 { $$ = zend_ast_create_assign_op(ZEND_CONCAT, $1, $3); } 1123 | variable T_MOD_EQUAL expr 1124 { $$ = zend_ast_create_assign_op(ZEND_MOD, $1, $3); } 1125 | variable T_AND_EQUAL expr 1126 { $$ = zend_ast_create_assign_op(ZEND_BW_AND, $1, $3); } 1127 | variable T_OR_EQUAL expr 1128 { $$ = zend_ast_create_assign_op(ZEND_BW_OR, $1, $3); } 1129 | variable T_XOR_EQUAL expr 1130 { $$ = zend_ast_create_assign_op(ZEND_BW_XOR, $1, $3); } 1131 | variable T_SL_EQUAL expr 1132 { $$ = zend_ast_create_assign_op(ZEND_SL, $1, $3); } 1133 | variable T_SR_EQUAL expr 1134 { $$ = zend_ast_create_assign_op(ZEND_SR, $1, $3); } 1135 | variable T_COALESCE_EQUAL expr 1136 { $$ = zend_ast_create(ZEND_AST_ASSIGN_COALESCE, $1, $3); } 1137 | variable T_INC { $$ = zend_ast_create(ZEND_AST_POST_INC, $1); } 1138 | T_INC variable { $$ = zend_ast_create(ZEND_AST_PRE_INC, $2); } 1139 | variable T_DEC { $$ = zend_ast_create(ZEND_AST_POST_DEC, $1); } 1140 | T_DEC variable { $$ = zend_ast_create(ZEND_AST_PRE_DEC, $2); } 1141 | expr T_BOOLEAN_OR expr 1142 { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); } 1143 | expr T_BOOLEAN_AND expr 1144 { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); } 1145 | expr T_LOGICAL_OR expr 1146 { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); } 1147 | expr T_LOGICAL_AND expr 1148 { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); } 1149 | expr T_LOGICAL_XOR expr 1150 { $$ = zend_ast_create_binary_op(ZEND_BOOL_XOR, $1, $3); } 1151 | expr '|' expr { $$ = zend_ast_create_binary_op(ZEND_BW_OR, $1, $3); } 1152 | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); } 1153 | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); } 1154 | expr '^' expr { $$ = zend_ast_create_binary_op(ZEND_BW_XOR, $1, $3); } 1155 | expr '.' expr { $$ = zend_ast_create_concat_op($1, $3); } 1156 | expr '+' expr { $$ = zend_ast_create_binary_op(ZEND_ADD, $1, $3); } 1157 | expr '-' expr { $$ = zend_ast_create_binary_op(ZEND_SUB, $1, $3); } 1158 | expr '*' expr { $$ = zend_ast_create_binary_op(ZEND_MUL, $1, $3); } 1159 | expr T_POW expr { $$ = zend_ast_create_binary_op(ZEND_POW, $1, $3); } 1160 | expr '/' expr { $$ = zend_ast_create_binary_op(ZEND_DIV, $1, $3); } 1161 | expr '%' expr { $$ = zend_ast_create_binary_op(ZEND_MOD, $1, $3); } 1162 | expr T_SL expr { $$ = zend_ast_create_binary_op(ZEND_SL, $1, $3); } 1163 | expr T_SR expr { $$ = zend_ast_create_binary_op(ZEND_SR, $1, $3); } 1164 | '+' expr %prec '~' { $$ = zend_ast_create(ZEND_AST_UNARY_PLUS, $2); } 1165 | '-' expr %prec '~' { $$ = zend_ast_create(ZEND_AST_UNARY_MINUS, $2); } 1166 | '!' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2); } 1167 | '~' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BW_NOT, $2); } 1168 | expr T_IS_IDENTICAL expr 1169 { $$ = zend_ast_create_binary_op(ZEND_IS_IDENTICAL, $1, $3); } 1170 | expr T_IS_NOT_IDENTICAL expr 1171 { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_IDENTICAL, $1, $3); } 1172 | expr T_IS_EQUAL expr 1173 { $$ = zend_ast_create_binary_op(ZEND_IS_EQUAL, $1, $3); } 1174 | expr T_IS_NOT_EQUAL expr 1175 { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_EQUAL, $1, $3); } 1176 | expr '<' expr 1177 { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER, $1, $3); } 1178 | expr T_IS_SMALLER_OR_EQUAL expr 1179 { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER_OR_EQUAL, $1, $3); } 1180 | expr '>' expr 1181 { $$ = zend_ast_create(ZEND_AST_GREATER, $1, $3); } 1182 | expr T_IS_GREATER_OR_EQUAL expr 1183 { $$ = zend_ast_create(ZEND_AST_GREATER_EQUAL, $1, $3); } 1184 | expr T_SPACESHIP expr 1185 { $$ = zend_ast_create_binary_op(ZEND_SPACESHIP, $1, $3); } 1186 | expr T_INSTANCEOF class_name_reference 1187 { $$ = zend_ast_create(ZEND_AST_INSTANCEOF, $1, $3); } 1188 | '(' expr ')' { 1189 $$ = $2; 1190 if ($$->kind == ZEND_AST_CONDITIONAL) $$->attr = ZEND_PARENTHESIZED_CONDITIONAL; 1191 } 1192 | new_expr { $$ = $1; } 1193 | expr '?' expr ':' expr 1194 { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); } 1195 | expr '?' ':' expr 1196 { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); } 1197 | expr T_COALESCE expr 1198 { $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); } 1199 | internal_functions_in_yacc { $$ = $1; } 1200 | T_INT_CAST expr { $$ = zend_ast_create_cast(IS_LONG, $2); } 1201 | T_DOUBLE_CAST expr { $$ = zend_ast_create_cast(IS_DOUBLE, $2); } 1202 | T_STRING_CAST expr { $$ = zend_ast_create_cast(IS_STRING, $2); } 1203 | T_ARRAY_CAST expr { $$ = zend_ast_create_cast(IS_ARRAY, $2); } 1204 | T_OBJECT_CAST expr { $$ = zend_ast_create_cast(IS_OBJECT, $2); } 1205 | T_BOOL_CAST expr { $$ = zend_ast_create_cast(_IS_BOOL, $2); } 1206 | T_UNSET_CAST expr { $$ = zend_ast_create_cast(IS_NULL, $2); } 1207 | T_EXIT exit_expr { $$ = zend_ast_create(ZEND_AST_EXIT, $2); } 1208 | '@' expr { $$ = zend_ast_create(ZEND_AST_SILENCE, $2); } 1209 | scalar { $$ = $1; } 1210 | '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); } 1211 | T_PRINT expr { $$ = zend_ast_create(ZEND_AST_PRINT, $2); } 1212 | T_YIELD { $$ = zend_ast_create(ZEND_AST_YIELD, NULL, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1213 | T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1214 | T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1215 | T_YIELD_FROM expr { $$ = zend_ast_create(ZEND_AST_YIELD_FROM, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1216 | T_THROW expr { $$ = zend_ast_create(ZEND_AST_THROW, $2); } 1217 | inline_function { $$ = $1; } 1218 | attributes inline_function { $$ = zend_ast_with_attributes($2, $1); } 1219 | T_STATIC inline_function { $$ = $2; ((zend_ast_decl *) $$)->flags |= ZEND_ACC_STATIC; } 1220 | attributes T_STATIC inline_function 1221 { $$ = zend_ast_with_attributes($3, $1); ((zend_ast_decl *) $$)->flags |= ZEND_ACC_STATIC; } 1222 | match { $$ = $1; } 1223 ; 1224 1225 1226 inline_function: 1227 function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type 1228 backup_fn_flags '{' inner_statement_list '}' backup_fn_flags 1229 { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2 | $13, $1, $3, 1230 zend_string_init("{closure}", sizeof("{closure}") - 1, 0), 1231 $5, $7, $11, $8, NULL); CG(extra_fn_flags) = $9; } 1232 | fn returns_ref backup_doc_comment '(' parameter_list ')' return_type 1233 T_DOUBLE_ARROW backup_fn_flags backup_lex_pos expr backup_fn_flags 1234 { $$ = zend_ast_create_decl(ZEND_AST_ARROW_FUNC, $2 | $12, $1, $3, 1235 zend_string_init("{closure}", sizeof("{closure}") - 1, 0), $5, NULL, $11, $7, NULL); 1236 ((zend_ast_decl *) $$)->lex_pos = $10; 1237 CG(extra_fn_flags) = $9; } 1238 ; 1239 1240 fn: 1241 T_FN { $$ = CG(zend_lineno); } 1242 ; 1243 1244 function: 1245 T_FUNCTION { $$ = CG(zend_lineno); } 1246 ; 1247 1248 backup_doc_comment: 1249 %empty { $$ = CG(doc_comment); CG(doc_comment) = NULL; } 1250 ; 1251 1252 backup_fn_flags: 1253 %prec PREC_ARROW_FUNCTION %empty { $$ = CG(extra_fn_flags); CG(extra_fn_flags) = 0; } 1254 ; 1255 1256 backup_lex_pos: 1257 %empty { $$ = LANG_SCNG(yy_text); } 1258 ; 1259 1260 returns_ref: 1261 %empty { $$ = 0; } 1262 | ampersand { $$ = ZEND_ACC_RETURN_REFERENCE; } 1263 ; 1264 1265 lexical_vars: 1266 %empty { $$ = NULL; } 1267 | T_USE '(' lexical_var_list possible_comma ')' { $$ = $3; } 1268 ; 1269 1270 lexical_var_list: 1271 lexical_var_list ',' lexical_var { $$ = zend_ast_list_add($1, $3); } 1272 | lexical_var { $$ = zend_ast_create_list(1, ZEND_AST_CLOSURE_USES, $1); } 1273 ; 1274 1275 lexical_var: 1276 T_VARIABLE { $$ = $1; } 1277 | ampersand T_VARIABLE { $$ = $2; $$->attr = ZEND_BIND_REF; } 1278 ; 1279 1280 function_call: 1281 name argument_list 1282 { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); } 1283 | T_READONLY argument_list { 1284 zval zv; 1285 if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } 1286 $$ = zend_ast_create(ZEND_AST_CALL, zend_ast_create_zval(&zv), $2); 1287 } 1288 | class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list 1289 { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } 1290 | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list 1291 { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } 1292 | callable_expr { $<num>$ = CG(zend_lineno); } argument_list { 1293 $$ = zend_ast_create(ZEND_AST_CALL, $1, $3); 1294 $$->lineno = $<num>2; 1295 } 1296 ; 1297 1298 class_name: 1299 T_STATIC 1300 { zval zv; ZVAL_INTERNED_STR(&zv, ZSTR_KNOWN(ZEND_STR_STATIC)); 1301 $$ = zend_ast_create_zval_ex(&zv, ZEND_NAME_NOT_FQ); } 1302 | name { $$ = $1; } 1303 ; 1304 1305 class_name_reference: 1306 class_name { $$ = $1; } 1307 | new_variable { $$ = $1; } 1308 | '(' expr ')' { $$ = $2; } 1309 ; 1310 1311 exit_expr: 1312 %empty { $$ = NULL; } 1313 | '(' optional_expr ')' { $$ = $2; } 1314 ; 1315 1316 backticks_expr: 1317 %empty 1318 { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); } 1319 | T_ENCAPSED_AND_WHITESPACE { $$ = $1; } 1320 | encaps_list { $$ = $1; } 1321 ; 1322 1323 1324 ctor_arguments: 1325 %empty { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); } 1326 | argument_list { $$ = $1; } 1327 ; 1328 1329 1330 dereferenceable_scalar: 1331 T_ARRAY '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LONG; } 1332 | '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; } 1333 | T_CONSTANT_ENCAPSED_STRING { $$ = $1; } 1334 | '"' encaps_list '"' { $$ = $2; } 1335 ; 1336 1337 scalar: 1338 T_LNUMBER { $$ = $1; } 1339 | T_DNUMBER { $$ = $1; } 1340 | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; } 1341 | T_START_HEREDOC T_END_HEREDOC 1342 { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); } 1343 | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; } 1344 | dereferenceable_scalar { $$ = $1; } 1345 | constant { $$ = $1; } 1346 | class_constant { $$ = $1; } 1347 ; 1348 1349 constant: 1350 name { $$ = zend_ast_create(ZEND_AST_CONST, $1); } 1351 | T_LINE { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_LINE); } 1352 | T_FILE { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FILE); } 1353 | T_DIR { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_DIR); } 1354 | T_TRAIT_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_TRAIT_C); } 1355 | T_METHOD_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_METHOD_C); } 1356 | T_FUNC_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FUNC_C); } 1357 | T_NS_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_NS_C); } 1358 | T_CLASS_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_CLASS_C); } 1359 ; 1360 1361 class_constant: 1362 class_name T_PAAMAYIM_NEKUDOTAYIM identifier 1363 { $$ = zend_ast_create_class_const_or_name($1, $3); } 1364 | variable_class_name T_PAAMAYIM_NEKUDOTAYIM identifier 1365 { $$ = zend_ast_create_class_const_or_name($1, $3); } 1366 ; 1367 1368 optional_expr: 1369 %empty { $$ = NULL; } 1370 | expr { $$ = $1; } 1371 ; 1372 1373 variable_class_name: 1374 fully_dereferenceable { $$ = $1; } 1375 ; 1376 1377 fully_dereferenceable: 1378 variable { $$ = $1; } 1379 | '(' expr ')' { $$ = $2; } 1380 | dereferenceable_scalar { $$ = $1; } 1381 | class_constant { $$ = $1; } 1382 ; 1383 1384 array_object_dereferenceable: 1385 fully_dereferenceable { $$ = $1; } 1386 | constant { $$ = $1; } 1387 ; 1388 1389 callable_expr: 1390 callable_variable { $$ = $1; } 1391 | '(' expr ')' { $$ = $2; } 1392 | dereferenceable_scalar { $$ = $1; } 1393 ; 1394 1395 callable_variable: 1396 simple_variable 1397 { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1398 | array_object_dereferenceable '[' optional_expr ']' 1399 { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); } 1400 | array_object_dereferenceable '{' expr '}' 1401 { $$ = zend_ast_create_ex(ZEND_AST_DIM, ZEND_DIM_ALTERNATIVE_SYNTAX, $1, $3); } 1402 | array_object_dereferenceable T_OBJECT_OPERATOR property_name argument_list 1403 { $$ = zend_ast_create(ZEND_AST_METHOD_CALL, $1, $3, $4); } 1404 | array_object_dereferenceable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list 1405 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_METHOD_CALL, $1, $3, $4); } 1406 | function_call { $$ = $1; } 1407 ; 1408 1409 variable: 1410 callable_variable 1411 { $$ = $1; } 1412 | static_member 1413 { $$ = $1; } 1414 | array_object_dereferenceable T_OBJECT_OPERATOR property_name 1415 { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); } 1416 | array_object_dereferenceable T_NULLSAFE_OBJECT_OPERATOR property_name 1417 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_PROP, $1, $3); } 1418 ; 1419 1420 simple_variable: 1421 T_VARIABLE { $$ = $1; } 1422 | '$' '{' expr '}' { $$ = $3; } 1423 | '$' simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $2); } 1424 ; 1425 1426 static_member: 1427 class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable 1428 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1429 | variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable 1430 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1431 ; 1432 1433 new_variable: 1434 simple_variable 1435 { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1436 | new_variable '[' optional_expr ']' 1437 { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); } 1438 | new_variable '{' expr '}' 1439 { $$ = zend_ast_create_ex(ZEND_AST_DIM, ZEND_DIM_ALTERNATIVE_SYNTAX, $1, $3); } 1440 | new_variable T_OBJECT_OPERATOR property_name 1441 { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); } 1442 | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name 1443 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_PROP, $1, $3); } 1444 | class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable 1445 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1446 | new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable 1447 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1448 ; 1449 1450 member_name: 1451 identifier { $$ = $1; } 1452 | '{' expr '}' { $$ = $2; } 1453 | simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1454 ; 1455 1456 property_name: 1457 T_STRING { $$ = $1; } 1458 | '{' expr '}' { $$ = $2; } 1459 | simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1460 ; 1461 1462 array_pair_list: 1463 non_empty_array_pair_list 1464 { /* allow single trailing comma */ $$ = zend_ast_list_rtrim($1); } 1465 ; 1466 1467 possible_array_pair: 1468 %empty { $$ = NULL; } 1469 | array_pair { $$ = $1; } 1470 ; 1471 1472 non_empty_array_pair_list: 1473 non_empty_array_pair_list ',' possible_array_pair 1474 { $$ = zend_ast_list_add($1, $3); } 1475 | possible_array_pair 1476 { $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, $1); } 1477 ; 1478 1479 array_pair: 1480 expr T_DOUBLE_ARROW expr 1481 { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); } 1482 | expr 1483 { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $1, NULL); } 1484 | expr T_DOUBLE_ARROW ampersand variable 1485 { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $4, $1); } 1486 | ampersand variable 1487 { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $2, NULL); } 1488 | T_ELLIPSIS expr 1489 { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); } 1490 | expr T_DOUBLE_ARROW T_LIST '(' array_pair_list ')' 1491 { $5->attr = ZEND_ARRAY_SYNTAX_LIST; 1492 $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); } 1493 | T_LIST '(' array_pair_list ')' 1494 { $3->attr = ZEND_ARRAY_SYNTAX_LIST; 1495 $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, NULL); } 1496 ; 1497 1498 encaps_list: 1499 encaps_list encaps_var 1500 { $$ = zend_ast_list_add($1, $2); } 1501 | encaps_list T_ENCAPSED_AND_WHITESPACE 1502 { $$ = zend_ast_list_add($1, $2); } 1503 | encaps_var 1504 { $$ = zend_ast_create_list(1, ZEND_AST_ENCAPS_LIST, $1); } 1505 | T_ENCAPSED_AND_WHITESPACE encaps_var 1506 { $$ = zend_ast_create_list(2, ZEND_AST_ENCAPS_LIST, $1, $2); } 1507 ; 1508 1509 encaps_var: 1510 T_VARIABLE 1511 { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1512 | T_VARIABLE '[' encaps_var_offset ']' 1513 { $$ = zend_ast_create(ZEND_AST_DIM, 1514 zend_ast_create(ZEND_AST_VAR, $1), $3); } 1515 | T_VARIABLE T_OBJECT_OPERATOR T_STRING 1516 { $$ = zend_ast_create(ZEND_AST_PROP, 1517 zend_ast_create(ZEND_AST_VAR, $1), $3); } 1518 | T_VARIABLE T_NULLSAFE_OBJECT_OPERATOR T_STRING 1519 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_PROP, 1520 zend_ast_create(ZEND_AST_VAR, $1), $3); } 1521 | T_DOLLAR_OPEN_CURLY_BRACES expr '}' 1522 { $$ = zend_ast_create_ex(ZEND_AST_VAR, ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR, $2); } 1523 | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' 1524 { $$ = zend_ast_create_ex(ZEND_AST_VAR, ZEND_ENCAPS_VAR_DOLLAR_CURLY, $2); } 1525 | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' 1526 { $$ = zend_ast_create_ex(ZEND_AST_DIM, ZEND_ENCAPS_VAR_DOLLAR_CURLY, 1527 zend_ast_create(ZEND_AST_VAR, $2), $4); } 1528 | T_CURLY_OPEN variable '}' { $$ = $2; } 1529 ; 1530 1531 encaps_var_offset: 1532 T_STRING { $$ = $1; } 1533 | T_NUM_STRING { $$ = $1; } 1534 | '-' T_NUM_STRING { $$ = zend_negate_num_string($2); } 1535 | T_VARIABLE { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1536 ; 1537 1538 1539 internal_functions_in_yacc: 1540 T_ISSET '(' isset_variables possible_comma ')' { $$ = $3; } 1541 | T_EMPTY '(' expr ')' { $$ = zend_ast_create(ZEND_AST_EMPTY, $3); } 1542 | T_INCLUDE expr 1543 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2); } 1544 | T_INCLUDE_ONCE expr 1545 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2); } 1546 | T_EVAL '(' expr ')' 1547 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, $3); } 1548 | T_REQUIRE expr 1549 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2); } 1550 | T_REQUIRE_ONCE expr 1551 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2); } 1552 ; 1553 1554 isset_variables: 1555 isset_variable { $$ = $1; } 1556 | isset_variables ',' isset_variable 1557 { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); } 1558 ; 1559 1560 isset_variable: 1561 expr { $$ = zend_ast_create(ZEND_AST_ISSET, $1); } 1562 ; 1563 1564 %% 1565 1566 /* Over-ride Bison formatting routine to give better token descriptions. 1567 Copy to YYRES the contents of YYSTR for use in yyerror. 1568 YYSTR is taken from yytname, from the %token declaration. 1569 If YYRES is null, do not copy; instead, return the length of what 1570 the result would have been. */ 1571 static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) 1572 { 1573 const char *toktype = yystr; 1574 size_t toktype_len = strlen(toktype); 1575 1576 /* CG(parse_error) states: 1577 * 0 => yyres = NULL, yystr is the unexpected token 1578 * 1 => yyres = NULL, yystr is one of the expected tokens 1579 * 2 => yyres != NULL, yystr is the unexpected token 1580 * 3 => yyres != NULL, yystr is one of the expected tokens 1581 */ 1582 if (yyres && CG(parse_error) < 2) { 1583 CG(parse_error) = 2; 1584 } 1585 1586 if (CG(parse_error) % 2 == 0) { 1587 /* The unexpected token */ 1588 char buffer[120]; 1589 const unsigned char *tokcontent, *tokcontent_end; 1590 size_t tokcontent_len; 1591 1592 CG(parse_error)++; 1593 1594 if (LANG_SCNG(yy_text)[0] == 0 && 1595 LANG_SCNG(yy_leng) == 1 && 1596 strcmp(toktype, "\"end of file\"") == 0) { 1597 if (yyres) { 1598 yystpcpy(yyres, "end of file"); 1599 } 1600 return sizeof("end of file")-1; 1601 } 1602 1603 /* Prevent the backslash getting doubled in the output (eugh) */ 1604 if (strcmp(toktype, "\"'\\\\'\"") == 0) { 1605 if (yyres) { 1606 yystpcpy(yyres, "token \"\\\""); 1607 } 1608 return sizeof("token \"\\\"")-1; 1609 } 1610 1611 /* We used "amp" as a dummy label to avoid a duplicate token literal warning. */ 1612 if (strcmp(toktype, "\"amp\"") == 0) { 1613 if (yyres) { 1614 yystpcpy(yyres, "token \"&\""); 1615 } 1616 return sizeof("token \"&\"")-1; 1617 } 1618 1619 /* Avoid unreadable """ */ 1620 /* "'" would theoretically be just as bad, but is never currently parsed as a separate token */ 1621 if (strcmp(toktype, "'\"'") == 0) { 1622 if (yyres) { 1623 yystpcpy(yyres, "double-quote mark"); 1624 } 1625 return sizeof("double-quote mark")-1; 1626 } 1627 1628 /* Strip off the outer quote marks */ 1629 if (toktype_len >= 2 && *toktype == '"') { 1630 toktype++; 1631 toktype_len -= 2; 1632 } 1633 1634 /* If the token always has one form, the %token line should have a single-quoted name */ 1635 /* The parser rules also include single-character un-named tokens which will be single-quoted here */ 1636 /* We re-format this with double quotes here to ensure everything's consistent */ 1637 if (toktype_len > 0 && *toktype == '\'') { 1638 if (yyres) { 1639 snprintf(buffer, sizeof(buffer), "token \"%.*s\"", (int)toktype_len-2, toktype+1); 1640 yystpcpy(yyres, buffer); 1641 } 1642 return toktype_len + sizeof("token ")-1; 1643 } 1644 1645 /* Fetch the content of the last seen token from global lexer state */ 1646 tokcontent = LANG_SCNG(yy_text); 1647 tokcontent_len = LANG_SCNG(yy_leng); 1648 1649 /* For T_BAD_CHARACTER, the content probably won't be a printable char */ 1650 /* Also, "unexpected invalid character" sounds a bit redundant */ 1651 if (tokcontent_len == 1 && strcmp(yystr, "\"invalid character\"") == 0) { 1652 if (yyres) { 1653 snprintf(buffer, sizeof(buffer), "character 0x%02hhX", *tokcontent); 1654 yystpcpy(yyres, buffer); 1655 } 1656 return sizeof("character 0x00")-1; 1657 } 1658 1659 /* Truncate at line end to avoid messing up log formats */ 1660 tokcontent_end = memchr(tokcontent, '\n', tokcontent_len); 1661 if (tokcontent_end != NULL) { 1662 tokcontent_len = (tokcontent_end - tokcontent); 1663 } 1664 1665 /* Try to be helpful about what kind of string was found, before stripping the quotes */ 1666 if (tokcontent_len > 0 && strcmp(yystr, "\"quoted string\"") == 0) { 1667 if (*tokcontent == '"') { 1668 toktype = "double-quoted string"; 1669 toktype_len = sizeof("double-quoted string")-1; 1670 } 1671 else if (*tokcontent == '\'') { 1672 toktype = "single-quoted string"; 1673 toktype_len = sizeof("single-quoted string")-1; 1674 } 1675 } 1676 1677 /* For quoted strings, strip off another layer of quotes to avoid putting quotes inside quotes */ 1678 if (tokcontent_len > 0 && (*tokcontent == '\'' || *tokcontent=='"')) { 1679 tokcontent++; 1680 tokcontent_len--; 1681 } 1682 if (tokcontent_len > 0 && (tokcontent[tokcontent_len-1] == '\'' || tokcontent[tokcontent_len-1] == '"')) { 1683 tokcontent_len--; 1684 } 1685 1686 /* Truncate to 30 characters and add a ... */ 1687 if (tokcontent_len > 30 + sizeof("...")-1) { 1688 if (yyres) { 1689 snprintf(buffer, sizeof(buffer), "%.*s \"%.*s...\"", (int)toktype_len, toktype, 30, tokcontent); 1690 yystpcpy(yyres, buffer); 1691 } 1692 return toktype_len + 30 + sizeof(" \"...\"")-1; 1693 } 1694 1695 if (yyres) { 1696 snprintf(buffer, sizeof(buffer), "%.*s \"%.*s\"", (int)toktype_len, toktype, (int)tokcontent_len, tokcontent); 1697 yystpcpy(yyres, buffer); 1698 } 1699 return toktype_len + tokcontent_len + sizeof(" \"\"")-1; 1700 } 1701 1702 /* One of the expected tokens */ 1703 1704 /* Prevent the backslash getting doubled in the output (eugh) */ 1705 if (strcmp(toktype, "\"'\\\\'\"") == 0) { 1706 if (yyres) { 1707 yystpcpy(yyres, "\"\\\""); 1708 } 1709 return sizeof("\"\\\"")-1; 1710 } 1711 1712 /* Strip off the outer quote marks */ 1713 if (toktype_len >= 2 && *toktype == '"') { 1714 toktype++; 1715 toktype_len -= 2; 1716 } 1717 1718 if (yyres) { 1719 YYSIZE_T yyn = 0; 1720 1721 for (; yyn < toktype_len; ++yyn) { 1722 /* Replace single quotes with double for consistency */ 1723 if (toktype[yyn] == '\'') { 1724 yyres[yyn] = '"'; 1725 } 1726 else { 1727 yyres[yyn] = toktype[yyn]; 1728 } 1729 } 1730 yyres[toktype_len] = '\0'; 1731 } 1732 1733 return toktype_len; 1734 } 1735