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