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 non_empty_member_modifiers 282 283 %type <num> returns_ref function fn is_reference is_variadic property_modifiers 284 %type <num> method_modifiers class_const_modifiers member_modifier optional_cpp_modifiers 285 %type <num> class_modifiers class_modifier anonymous_class_modifiers anonymous_class_modifiers_optional 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; (void) zendnerrs; } 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_name: 564 T_STRING { $$ = $1; } 565 | T_READONLY { 566 zval zv; 567 if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } 568 $$ = zend_ast_create_zval(&zv); 569 } 570 ; 571 572 function_declaration_statement: 573 function returns_ref function_name backup_doc_comment '(' parameter_list ')' return_type 574 backup_fn_flags '{' inner_statement_list '}' backup_fn_flags 575 { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2 | $13, $1, $4, 576 zend_ast_get_str($3), $6, NULL, $11, $8, NULL); CG(extra_fn_flags) = $9; } 577 ; 578 579 is_reference: 580 %empty { $$ = 0; } 581 | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = ZEND_PARAM_REF; } 582 ; 583 584 is_variadic: 585 %empty { $$ = 0; } 586 | T_ELLIPSIS { $$ = ZEND_PARAM_VARIADIC; } 587 ; 588 589 class_declaration_statement: 590 class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); } 591 T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' 592 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>3, $7, zend_ast_get_str($4), $5, $6, $9, NULL, NULL); } 593 | T_CLASS { $<num>$ = CG(zend_lineno); } 594 T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' 595 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>2, $6, zend_ast_get_str($3), $4, $5, $8, NULL, NULL); } 596 ; 597 598 class_modifiers: 599 class_modifier { $$ = $1; } 600 | class_modifiers class_modifier 601 { $$ = zend_add_class_modifier($1, $2); if (!$$) { YYERROR; } } 602 ; 603 604 anonymous_class_modifiers: 605 class_modifier 606 { $$ = zend_add_anonymous_class_modifier(0, $1); if (!$$) { YYERROR; } } 607 | anonymous_class_modifiers class_modifier 608 { $$ = zend_add_anonymous_class_modifier($1, $2); if (!$$) { YYERROR; } } 609 ; 610 611 anonymous_class_modifiers_optional: 612 %empty { $$ = 0; } 613 | anonymous_class_modifiers { $$ = $1; } 614 ; 615 616 class_modifier: 617 T_ABSTRACT { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } 618 | T_FINAL { $$ = ZEND_ACC_FINAL; } 619 | T_READONLY { $$ = ZEND_ACC_READONLY_CLASS|ZEND_ACC_NO_DYNAMIC_PROPERTIES; } 620 ; 621 622 trait_declaration_statement: 623 T_TRAIT { $<num>$ = CG(zend_lineno); } 624 T_STRING backup_doc_comment '{' class_statement_list '}' 625 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $<num>2, $4, zend_ast_get_str($3), NULL, NULL, $6, NULL, NULL); } 626 ; 627 628 interface_declaration_statement: 629 T_INTERFACE { $<num>$ = CG(zend_lineno); } 630 T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}' 631 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5, zend_ast_get_str($3), NULL, $4, $7, NULL, NULL); } 632 ; 633 634 enum_declaration_statement: 635 T_ENUM { $<num>$ = CG(zend_lineno); } 636 T_STRING enum_backing_type implements_list backup_doc_comment '{' class_statement_list '}' 637 { $$ = 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); } 638 ; 639 640 enum_backing_type: 641 %empty { $$ = NULL; } 642 | ':' type_expr { $$ = $2; } 643 ; 644 645 enum_case: 646 T_CASE backup_doc_comment identifier enum_case_expr ';' 647 { $$ = zend_ast_create(ZEND_AST_ENUM_CASE, $3, $4, ($2 ? zend_ast_create_zval_from_str($2) : NULL), NULL); } 648 ; 649 650 enum_case_expr: 651 %empty { $$ = NULL; } 652 | '=' expr { $$ = $2; } 653 ; 654 655 extends_from: 656 %empty { $$ = NULL; } 657 | T_EXTENDS class_name { $$ = $2; } 658 ; 659 660 interface_extends_list: 661 %empty { $$ = NULL; } 662 | T_EXTENDS class_name_list { $$ = $2; } 663 ; 664 665 implements_list: 666 %empty { $$ = NULL; } 667 | T_IMPLEMENTS class_name_list { $$ = $2; } 668 ; 669 670 foreach_variable: 671 variable { $$ = $1; } 672 | ampersand variable { $$ = zend_ast_create(ZEND_AST_REF, $2); } 673 | T_LIST '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LIST; } 674 | '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; } 675 ; 676 677 for_statement: 678 statement { $$ = $1; } 679 | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } 680 ; 681 682 foreach_statement: 683 statement { $$ = $1; } 684 | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } 685 ; 686 687 declare_statement: 688 statement { $$ = $1; } 689 | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } 690 ; 691 692 switch_case_list: 693 '{' case_list '}' { $$ = $2; } 694 | '{' ';' case_list '}' { $$ = $3; } 695 | ':' case_list T_ENDSWITCH ';' { $$ = $2; } 696 | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } 697 ; 698 699 case_list: 700 %empty { $$ = zend_ast_create_list(0, ZEND_AST_SWITCH_LIST); } 701 | case_list T_CASE expr case_separator inner_statement_list 702 { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, $3, $5)); } 703 | case_list T_DEFAULT case_separator inner_statement_list 704 { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, NULL, $4)); } 705 ; 706 707 case_separator: 708 ':' 709 | ';' 710 ; 711 712 713 match: 714 T_MATCH '(' expr ')' '{' match_arm_list '}' 715 { $$ = zend_ast_create(ZEND_AST_MATCH, $3, $6); }; 716 ; 717 718 match_arm_list: 719 %empty { $$ = zend_ast_create_list(0, ZEND_AST_MATCH_ARM_LIST); } 720 | non_empty_match_arm_list possible_comma { $$ = $1; } 721 ; 722 723 non_empty_match_arm_list: 724 match_arm { $$ = zend_ast_create_list(1, ZEND_AST_MATCH_ARM_LIST, $1); } 725 | non_empty_match_arm_list ',' match_arm { $$ = zend_ast_list_add($1, $3); } 726 ; 727 728 match_arm: 729 match_arm_cond_list possible_comma T_DOUBLE_ARROW expr 730 { $$ = zend_ast_create(ZEND_AST_MATCH_ARM, $1, $4); } 731 | T_DEFAULT possible_comma T_DOUBLE_ARROW expr 732 { $$ = zend_ast_create(ZEND_AST_MATCH_ARM, NULL, $4); } 733 ; 734 735 match_arm_cond_list: 736 expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } 737 | match_arm_cond_list ',' expr { $$ = zend_ast_list_add($1, $3); } 738 ; 739 740 741 while_statement: 742 statement { $$ = $1; } 743 | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } 744 ; 745 746 747 if_stmt_without_else: 748 T_IF '(' expr ')' statement 749 { $$ = zend_ast_create_list(1, ZEND_AST_IF, 750 zend_ast_create(ZEND_AST_IF_ELEM, $3, $5)); } 751 | if_stmt_without_else T_ELSEIF '(' expr ')' statement 752 { $$ = zend_ast_list_add($1, 753 zend_ast_create(ZEND_AST_IF_ELEM, $4, $6)); } 754 ; 755 756 if_stmt: 757 if_stmt_without_else %prec T_NOELSE { $$ = $1; } 758 | if_stmt_without_else T_ELSE statement 759 { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_IF_ELEM, NULL, $3)); } 760 ; 761 762 alt_if_stmt_without_else: 763 T_IF '(' expr ')' ':' inner_statement_list 764 { $$ = zend_ast_create_list(1, ZEND_AST_IF, 765 zend_ast_create(ZEND_AST_IF_ELEM, $3, $6)); } 766 | alt_if_stmt_without_else T_ELSEIF '(' expr ')' ':' inner_statement_list 767 { $$ = zend_ast_list_add($1, 768 zend_ast_create(ZEND_AST_IF_ELEM, $4, $7)); } 769 ; 770 771 alt_if_stmt: 772 alt_if_stmt_without_else T_ENDIF ';' { $$ = $1; } 773 | alt_if_stmt_without_else T_ELSE ':' inner_statement_list T_ENDIF ';' 774 { $$ = zend_ast_list_add($1, 775 zend_ast_create(ZEND_AST_IF_ELEM, NULL, $4)); } 776 ; 777 778 parameter_list: 779 non_empty_parameter_list possible_comma { $$ = $1; } 780 | %empty { $$ = zend_ast_create_list(0, ZEND_AST_PARAM_LIST); } 781 ; 782 783 784 non_empty_parameter_list: 785 attributed_parameter 786 { $$ = zend_ast_create_list(1, ZEND_AST_PARAM_LIST, $1); } 787 | non_empty_parameter_list ',' attributed_parameter 788 { $$ = zend_ast_list_add($1, $3); } 789 ; 790 791 attributed_parameter: 792 attributes parameter { $$ = zend_ast_with_attributes($2, $1); } 793 | parameter { $$ = $1; } 794 ; 795 796 optional_cpp_modifiers: 797 %empty 798 { $$ = 0; } 799 | non_empty_member_modifiers 800 { $$ = zend_modifier_list_to_flags(ZEND_MODIFIER_TARGET_CPP, $1); 801 if (!$$) { YYERROR; } } 802 ; 803 804 parameter: 805 optional_cpp_modifiers optional_type_without_static 806 is_reference is_variadic T_VARIABLE backup_doc_comment 807 { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $1 | $3 | $4, $2, $5, NULL, 808 NULL, $6 ? zend_ast_create_zval_from_str($6) : NULL); } 809 | optional_cpp_modifiers optional_type_without_static 810 is_reference is_variadic T_VARIABLE backup_doc_comment '=' expr 811 { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $1 | $3 | $4, $2, $5, $8, 812 NULL, $6 ? zend_ast_create_zval_from_str($6) : NULL); } 813 ; 814 815 optional_type_without_static: 816 %empty { $$ = NULL; } 817 | type_expr_without_static { $$ = $1; } 818 ; 819 820 type_expr: 821 type { $$ = $1; } 822 | '?' type { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; } 823 | union_type { $$ = $1; } 824 | intersection_type { $$ = $1; } 825 ; 826 827 type: 828 type_without_static { $$ = $1; } 829 | T_STATIC { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_STATIC); } 830 ; 831 832 union_type_element: 833 type { $$ = $1; } 834 | '(' intersection_type ')' { $$ = $2; } 835 ; 836 837 union_type: 838 union_type_element '|' union_type_element 839 { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } 840 | union_type '|' union_type_element 841 { $$ = zend_ast_list_add($1, $3); } 842 ; 843 844 intersection_type: 845 type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_INTERSECTION, $1, $3); } 846 | intersection_type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { $$ = zend_ast_list_add($1, $3); } 847 ; 848 849 /* Duplicate the type rules without "static", 850 * to avoid conflicts with "static" modifier for properties. */ 851 852 type_expr_without_static: 853 type_without_static { $$ = $1; } 854 | '?' type_without_static { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; } 855 | union_type_without_static { $$ = $1; } 856 | intersection_type_without_static { $$ = $1; } 857 ; 858 859 type_without_static: 860 T_ARRAY { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); } 861 | T_CALLABLE { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_CALLABLE); } 862 | name { $$ = $1; } 863 ; 864 865 union_type_without_static_element: 866 type_without_static { $$ = $1; } 867 | '(' intersection_type_without_static ')' { $$ = $2; } 868 ; 869 870 union_type_without_static: 871 union_type_without_static_element '|' union_type_without_static_element 872 { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } 873 | union_type_without_static '|' union_type_without_static_element 874 { $$ = zend_ast_list_add($1, $3); } 875 ; 876 877 intersection_type_without_static: 878 type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static 879 { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_INTERSECTION, $1, $3); } 880 | intersection_type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static 881 { $$ = zend_ast_list_add($1, $3); } 882 ; 883 884 return_type: 885 %empty { $$ = NULL; } 886 | ':' type_expr { $$ = $2; } 887 ; 888 889 argument_list: 890 '(' ')' { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); } 891 | '(' non_empty_argument_list possible_comma ')' { $$ = $2; } 892 | '(' T_ELLIPSIS ')' { $$ = zend_ast_create(ZEND_AST_CALLABLE_CONVERT); } 893 ; 894 895 non_empty_argument_list: 896 argument 897 { $$ = zend_ast_create_list(1, ZEND_AST_ARG_LIST, $1); } 898 | non_empty_argument_list ',' argument 899 { $$ = zend_ast_list_add($1, $3); } 900 ; 901 902 argument: 903 expr { $$ = $1; } 904 | identifier ':' expr 905 { $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, $3); } 906 | T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); } 907 ; 908 909 global_var_list: 910 global_var_list ',' global_var { $$ = zend_ast_list_add($1, $3); } 911 | global_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } 912 ; 913 914 global_var: 915 simple_variable 916 { $$ = zend_ast_create(ZEND_AST_GLOBAL, zend_ast_create(ZEND_AST_VAR, $1)); } 917 ; 918 919 920 static_var_list: 921 static_var_list ',' static_var { $$ = zend_ast_list_add($1, $3); } 922 | static_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } 923 ; 924 925 static_var: 926 T_VARIABLE { $$ = zend_ast_create(ZEND_AST_STATIC, $1, NULL); } 927 | T_VARIABLE '=' expr { $$ = zend_ast_create(ZEND_AST_STATIC, $1, $3); } 928 ; 929 930 class_statement_list: 931 class_statement_list class_statement 932 { $$ = zend_ast_list_add($1, $2); } 933 | %empty 934 { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); } 935 ; 936 937 938 attributed_class_statement: 939 property_modifiers optional_type_without_static property_list ';' 940 { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3, NULL); 941 $$->attr = $1; } 942 | class_const_modifiers T_CONST class_const_list ';' 943 { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL, NULL); 944 $$->attr = $1; } 945 | class_const_modifiers T_CONST type_expr class_const_list ';' 946 { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $4, NULL, $3); 947 $$->attr = $1; } 948 | method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')' 949 return_type backup_fn_flags method_body backup_fn_flags 950 { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1 | $12, $2, $5, 951 zend_ast_get_str($4), $7, NULL, $11, $9, NULL); CG(extra_fn_flags) = $10; } 952 | enum_case { $$ = $1; } 953 ; 954 955 class_statement: 956 attributed_class_statement { $$ = $1; } 957 | attributes attributed_class_statement { $$ = zend_ast_with_attributes($2, $1); } 958 | T_USE class_name_list trait_adaptations 959 { $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); } 960 ; 961 962 class_name_list: 963 class_name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); } 964 | class_name_list ',' class_name { $$ = zend_ast_list_add($1, $3); } 965 ; 966 967 trait_adaptations: 968 ';' { $$ = NULL; } 969 | '{' '}' { $$ = NULL; } 970 | '{' trait_adaptation_list '}' { $$ = $2; } 971 ; 972 973 trait_adaptation_list: 974 trait_adaptation 975 { $$ = zend_ast_create_list(1, ZEND_AST_TRAIT_ADAPTATIONS, $1); } 976 | trait_adaptation_list trait_adaptation 977 { $$ = zend_ast_list_add($1, $2); } 978 ; 979 980 trait_adaptation: 981 trait_precedence ';' { $$ = $1; } 982 | trait_alias ';' { $$ = $1; } 983 ; 984 985 trait_precedence: 986 absolute_trait_method_reference T_INSTEADOF class_name_list 987 { $$ = zend_ast_create(ZEND_AST_TRAIT_PRECEDENCE, $1, $3); } 988 ; 989 990 trait_alias: 991 trait_method_reference T_AS T_STRING 992 { $$ = zend_ast_create(ZEND_AST_TRAIT_ALIAS, $1, $3); } 993 | trait_method_reference T_AS reserved_non_modifiers 994 { zval zv; 995 if (zend_lex_tstring(&zv, $3) == FAILURE) { YYABORT; } 996 $$ = zend_ast_create(ZEND_AST_TRAIT_ALIAS, $1, zend_ast_create_zval(&zv)); } 997 | trait_method_reference T_AS member_modifier identifier 998 { uint32_t modifiers = zend_modifier_token_to_flag(ZEND_MODIFIER_TARGET_METHOD, $3); 999 $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, modifiers, $1, $4); 1000 /* identifier nonterminal can cause allocations, so we need to free the node */ 1001 if (!modifiers) { zend_ast_destroy($$); YYERROR; } } 1002 | trait_method_reference T_AS member_modifier 1003 { uint32_t modifiers = zend_modifier_token_to_flag(ZEND_MODIFIER_TARGET_METHOD, $3); 1004 $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, modifiers, $1, NULL); 1005 /* identifier nonterminal can cause allocations, so we need to free the node */ 1006 if (!modifiers) { zend_ast_destroy($$); YYERROR; } } 1007 ; 1008 1009 trait_method_reference: 1010 identifier 1011 { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, NULL, $1); } 1012 | absolute_trait_method_reference { $$ = $1; } 1013 ; 1014 1015 absolute_trait_method_reference: 1016 class_name T_PAAMAYIM_NEKUDOTAYIM identifier 1017 { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, $1, $3); } 1018 ; 1019 1020 method_body: 1021 ';' /* abstract method */ { $$ = NULL; } 1022 | '{' inner_statement_list '}' { $$ = $2; } 1023 ; 1024 1025 property_modifiers: 1026 non_empty_member_modifiers 1027 { $$ = zend_modifier_list_to_flags(ZEND_MODIFIER_TARGET_PROPERTY, $1); 1028 if (!$$) { YYERROR; } } 1029 | T_VAR 1030 { $$ = ZEND_ACC_PUBLIC; } 1031 ; 1032 1033 method_modifiers: 1034 %empty 1035 { $$ = ZEND_ACC_PUBLIC; } 1036 | non_empty_member_modifiers 1037 { $$ = zend_modifier_list_to_flags(ZEND_MODIFIER_TARGET_METHOD, $1); 1038 if (!$$) { YYERROR; } 1039 if (!($$ & ZEND_ACC_PPP_MASK)) { $$ |= ZEND_ACC_PUBLIC; } } 1040 ; 1041 1042 class_const_modifiers: 1043 %empty 1044 { $$ = ZEND_ACC_PUBLIC; } 1045 | non_empty_member_modifiers 1046 { $$ = zend_modifier_list_to_flags(ZEND_MODIFIER_TARGET_CONSTANT, $1); 1047 if (!$$) { YYERROR; } 1048 if (!($$ & ZEND_ACC_PPP_MASK)) { $$ |= ZEND_ACC_PUBLIC; } } 1049 ; 1050 1051 non_empty_member_modifiers: 1052 member_modifier 1053 { $$ = zend_ast_create_list(1, ZEND_AST_MODIFIER_LIST, zend_ast_create_zval_from_long($1)); } 1054 | non_empty_member_modifiers member_modifier 1055 { $$ = zend_ast_list_add($1, zend_ast_create_zval_from_long($2)); } 1056 ; 1057 1058 member_modifier: 1059 T_PUBLIC { $$ = T_PUBLIC; } 1060 | T_PROTECTED { $$ = T_PROTECTED; } 1061 | T_PRIVATE { $$ = T_PRIVATE; } 1062 | T_STATIC { $$ = T_STATIC; } 1063 | T_ABSTRACT { $$ = T_ABSTRACT; } 1064 | T_FINAL { $$ = T_FINAL; } 1065 | T_READONLY { $$ = T_READONLY; } 1066 ; 1067 1068 property_list: 1069 property_list ',' property { $$ = zend_ast_list_add($1, $3); } 1070 | property { $$ = zend_ast_create_list(1, ZEND_AST_PROP_DECL, $1); } 1071 ; 1072 1073 property: 1074 T_VARIABLE backup_doc_comment 1075 { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, NULL, ($2 ? zend_ast_create_zval_from_str($2) : NULL)); } 1076 | T_VARIABLE '=' expr backup_doc_comment 1077 { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } 1078 ; 1079 1080 class_const_list: 1081 class_const_list ',' class_const_decl { $$ = zend_ast_list_add($1, $3); } 1082 | class_const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); } 1083 ; 1084 1085 class_const_decl: 1086 T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } 1087 | semi_reserved '=' expr backup_doc_comment { 1088 zval zv; 1089 if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } 1090 $$ = zend_ast_create(ZEND_AST_CONST_ELEM, zend_ast_create_zval(&zv), $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); 1091 } 1092 ; 1093 1094 const_decl: 1095 T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } 1096 ; 1097 1098 echo_expr_list: 1099 echo_expr_list ',' echo_expr { $$ = zend_ast_list_add($1, $3); } 1100 | echo_expr { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } 1101 ; 1102 echo_expr: 1103 expr { $$ = zend_ast_create(ZEND_AST_ECHO, $1); } 1104 ; 1105 1106 for_exprs: 1107 %empty { $$ = NULL; } 1108 | non_empty_for_exprs { $$ = $1; } 1109 ; 1110 1111 non_empty_for_exprs: 1112 non_empty_for_exprs ',' expr { $$ = zend_ast_list_add($1, $3); } 1113 | expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } 1114 ; 1115 1116 anonymous_class: 1117 anonymous_class_modifiers_optional T_CLASS { $<num>$ = CG(zend_lineno); } ctor_arguments 1118 extends_from implements_list backup_doc_comment '{' class_statement_list '}' { 1119 zend_ast *decl = zend_ast_create_decl( 1120 ZEND_AST_CLASS, ZEND_ACC_ANON_CLASS | $1, $<num>3, $7, NULL, 1121 $5, $6, $9, NULL, NULL); 1122 $$ = zend_ast_create(ZEND_AST_NEW, decl, $4); 1123 } 1124 ; 1125 1126 new_expr: 1127 T_NEW class_name_reference ctor_arguments 1128 { $$ = zend_ast_create(ZEND_AST_NEW, $2, $3); } 1129 | T_NEW anonymous_class 1130 { $$ = $2; } 1131 | T_NEW attributes anonymous_class 1132 { zend_ast_with_attributes($3->child[0], $2); $$ = $3; } 1133 ; 1134 1135 expr: 1136 variable 1137 { $$ = $1; } 1138 | T_LIST '(' array_pair_list ')' '=' expr 1139 { $3->attr = ZEND_ARRAY_SYNTAX_LIST; $$ = zend_ast_create(ZEND_AST_ASSIGN, $3, $6); } 1140 | '[' array_pair_list ']' '=' expr 1141 { $2->attr = ZEND_ARRAY_SYNTAX_SHORT; $$ = zend_ast_create(ZEND_AST_ASSIGN, $2, $5); } 1142 | variable '=' expr 1143 { $$ = zend_ast_create(ZEND_AST_ASSIGN, $1, $3); } 1144 | variable '=' ampersand variable 1145 { $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); } 1146 | T_CLONE expr { $$ = zend_ast_create(ZEND_AST_CLONE, $2); } 1147 | variable T_PLUS_EQUAL expr 1148 { $$ = zend_ast_create_assign_op(ZEND_ADD, $1, $3); } 1149 | variable T_MINUS_EQUAL expr 1150 { $$ = zend_ast_create_assign_op(ZEND_SUB, $1, $3); } 1151 | variable T_MUL_EQUAL expr 1152 { $$ = zend_ast_create_assign_op(ZEND_MUL, $1, $3); } 1153 | variable T_POW_EQUAL expr 1154 { $$ = zend_ast_create_assign_op(ZEND_POW, $1, $3); } 1155 | variable T_DIV_EQUAL expr 1156 { $$ = zend_ast_create_assign_op(ZEND_DIV, $1, $3); } 1157 | variable T_CONCAT_EQUAL expr 1158 { $$ = zend_ast_create_assign_op(ZEND_CONCAT, $1, $3); } 1159 | variable T_MOD_EQUAL expr 1160 { $$ = zend_ast_create_assign_op(ZEND_MOD, $1, $3); } 1161 | variable T_AND_EQUAL expr 1162 { $$ = zend_ast_create_assign_op(ZEND_BW_AND, $1, $3); } 1163 | variable T_OR_EQUAL expr 1164 { $$ = zend_ast_create_assign_op(ZEND_BW_OR, $1, $3); } 1165 | variable T_XOR_EQUAL expr 1166 { $$ = zend_ast_create_assign_op(ZEND_BW_XOR, $1, $3); } 1167 | variable T_SL_EQUAL expr 1168 { $$ = zend_ast_create_assign_op(ZEND_SL, $1, $3); } 1169 | variable T_SR_EQUAL expr 1170 { $$ = zend_ast_create_assign_op(ZEND_SR, $1, $3); } 1171 | variable T_COALESCE_EQUAL expr 1172 { $$ = zend_ast_create(ZEND_AST_ASSIGN_COALESCE, $1, $3); } 1173 | variable T_INC { $$ = zend_ast_create(ZEND_AST_POST_INC, $1); } 1174 | T_INC variable { $$ = zend_ast_create(ZEND_AST_PRE_INC, $2); } 1175 | variable T_DEC { $$ = zend_ast_create(ZEND_AST_POST_DEC, $1); } 1176 | T_DEC variable { $$ = zend_ast_create(ZEND_AST_PRE_DEC, $2); } 1177 | expr T_BOOLEAN_OR expr 1178 { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); } 1179 | expr T_BOOLEAN_AND expr 1180 { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); } 1181 | expr T_LOGICAL_OR expr 1182 { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); } 1183 | expr T_LOGICAL_AND expr 1184 { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); } 1185 | expr T_LOGICAL_XOR expr 1186 { $$ = zend_ast_create_binary_op(ZEND_BOOL_XOR, $1, $3); } 1187 | expr '|' expr { $$ = zend_ast_create_binary_op(ZEND_BW_OR, $1, $3); } 1188 | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); } 1189 | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); } 1190 | expr '^' expr { $$ = zend_ast_create_binary_op(ZEND_BW_XOR, $1, $3); } 1191 | expr '.' expr { $$ = zend_ast_create_concat_op($1, $3); } 1192 | expr '+' expr { $$ = zend_ast_create_binary_op(ZEND_ADD, $1, $3); } 1193 | expr '-' expr { $$ = zend_ast_create_binary_op(ZEND_SUB, $1, $3); } 1194 | expr '*' expr { $$ = zend_ast_create_binary_op(ZEND_MUL, $1, $3); } 1195 | expr T_POW expr { $$ = zend_ast_create_binary_op(ZEND_POW, $1, $3); } 1196 | expr '/' expr { $$ = zend_ast_create_binary_op(ZEND_DIV, $1, $3); } 1197 | expr '%' expr { $$ = zend_ast_create_binary_op(ZEND_MOD, $1, $3); } 1198 | expr T_SL expr { $$ = zend_ast_create_binary_op(ZEND_SL, $1, $3); } 1199 | expr T_SR expr { $$ = zend_ast_create_binary_op(ZEND_SR, $1, $3); } 1200 | '+' expr %prec '~' { $$ = zend_ast_create(ZEND_AST_UNARY_PLUS, $2); } 1201 | '-' expr %prec '~' { $$ = zend_ast_create(ZEND_AST_UNARY_MINUS, $2); } 1202 | '!' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2); } 1203 | '~' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BW_NOT, $2); } 1204 | expr T_IS_IDENTICAL expr 1205 { $$ = zend_ast_create_binary_op(ZEND_IS_IDENTICAL, $1, $3); } 1206 | expr T_IS_NOT_IDENTICAL expr 1207 { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_IDENTICAL, $1, $3); } 1208 | expr T_IS_EQUAL expr 1209 { $$ = zend_ast_create_binary_op(ZEND_IS_EQUAL, $1, $3); } 1210 | expr T_IS_NOT_EQUAL expr 1211 { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_EQUAL, $1, $3); } 1212 | expr '<' expr 1213 { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER, $1, $3); } 1214 | expr T_IS_SMALLER_OR_EQUAL expr 1215 { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER_OR_EQUAL, $1, $3); } 1216 | expr '>' expr 1217 { $$ = zend_ast_create(ZEND_AST_GREATER, $1, $3); } 1218 | expr T_IS_GREATER_OR_EQUAL expr 1219 { $$ = zend_ast_create(ZEND_AST_GREATER_EQUAL, $1, $3); } 1220 | expr T_SPACESHIP expr 1221 { $$ = zend_ast_create_binary_op(ZEND_SPACESHIP, $1, $3); } 1222 | expr T_INSTANCEOF class_name_reference 1223 { $$ = zend_ast_create(ZEND_AST_INSTANCEOF, $1, $3); } 1224 | '(' expr ')' { 1225 $$ = $2; 1226 if ($$->kind == ZEND_AST_CONDITIONAL) $$->attr = ZEND_PARENTHESIZED_CONDITIONAL; 1227 } 1228 | new_expr { $$ = $1; } 1229 | expr '?' expr ':' expr 1230 { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); } 1231 | expr '?' ':' expr 1232 { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); } 1233 | expr T_COALESCE expr 1234 { $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); } 1235 | internal_functions_in_yacc { $$ = $1; } 1236 | T_INT_CAST expr { $$ = zend_ast_create_cast(IS_LONG, $2); } 1237 | T_DOUBLE_CAST expr { $$ = zend_ast_create_cast(IS_DOUBLE, $2); } 1238 | T_STRING_CAST expr { $$ = zend_ast_create_cast(IS_STRING, $2); } 1239 | T_ARRAY_CAST expr { $$ = zend_ast_create_cast(IS_ARRAY, $2); } 1240 | T_OBJECT_CAST expr { $$ = zend_ast_create_cast(IS_OBJECT, $2); } 1241 | T_BOOL_CAST expr { $$ = zend_ast_create_cast(_IS_BOOL, $2); } 1242 | T_UNSET_CAST expr { $$ = zend_ast_create_cast(IS_NULL, $2); } 1243 | T_EXIT exit_expr { $$ = zend_ast_create(ZEND_AST_EXIT, $2); } 1244 | '@' expr { $$ = zend_ast_create(ZEND_AST_SILENCE, $2); } 1245 | scalar { $$ = $1; } 1246 | '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); } 1247 | T_PRINT expr { $$ = zend_ast_create(ZEND_AST_PRINT, $2); } 1248 | T_YIELD { $$ = zend_ast_create(ZEND_AST_YIELD, NULL, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1249 | T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1250 | T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1251 | T_YIELD_FROM expr { $$ = zend_ast_create(ZEND_AST_YIELD_FROM, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; } 1252 | T_THROW expr { $$ = zend_ast_create(ZEND_AST_THROW, $2); } 1253 | inline_function { $$ = $1; } 1254 | attributes inline_function { $$ = zend_ast_with_attributes($2, $1); } 1255 | T_STATIC inline_function { $$ = $2; ((zend_ast_decl *) $$)->flags |= ZEND_ACC_STATIC; } 1256 | attributes T_STATIC inline_function 1257 { $$ = zend_ast_with_attributes($3, $1); ((zend_ast_decl *) $$)->flags |= ZEND_ACC_STATIC; } 1258 | match { $$ = $1; } 1259 ; 1260 1261 1262 inline_function: 1263 function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type 1264 backup_fn_flags '{' inner_statement_list '}' backup_fn_flags 1265 { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2 | $13, $1, $3, 1266 ZSTR_INIT_LITERAL("{closure}", 0), 1267 $5, $7, $11, $8, NULL); CG(extra_fn_flags) = $9; } 1268 | fn returns_ref backup_doc_comment '(' parameter_list ')' return_type 1269 T_DOUBLE_ARROW backup_fn_flags backup_lex_pos expr backup_fn_flags 1270 { $$ = zend_ast_create_decl(ZEND_AST_ARROW_FUNC, $2 | $12, $1, $3, 1271 ZSTR_INIT_LITERAL("{closure}", 0), $5, NULL, $11, $7, NULL); 1272 CG(extra_fn_flags) = $9; } 1273 ; 1274 1275 fn: 1276 T_FN { $$ = CG(zend_lineno); } 1277 ; 1278 1279 function: 1280 T_FUNCTION { $$ = CG(zend_lineno); } 1281 ; 1282 1283 backup_doc_comment: 1284 %empty { $$ = CG(doc_comment); CG(doc_comment) = NULL; } 1285 ; 1286 1287 backup_fn_flags: 1288 %prec PREC_ARROW_FUNCTION %empty { $$ = CG(extra_fn_flags); CG(extra_fn_flags) = 0; } 1289 ; 1290 1291 backup_lex_pos: 1292 %empty { $$ = LANG_SCNG(yy_text); } 1293 ; 1294 1295 returns_ref: 1296 %empty { $$ = 0; } 1297 | ampersand { $$ = ZEND_ACC_RETURN_REFERENCE; } 1298 ; 1299 1300 lexical_vars: 1301 %empty { $$ = NULL; } 1302 | T_USE '(' lexical_var_list possible_comma ')' { $$ = $3; } 1303 ; 1304 1305 lexical_var_list: 1306 lexical_var_list ',' lexical_var { $$ = zend_ast_list_add($1, $3); } 1307 | lexical_var { $$ = zend_ast_create_list(1, ZEND_AST_CLOSURE_USES, $1); } 1308 ; 1309 1310 lexical_var: 1311 T_VARIABLE { $$ = $1; } 1312 | ampersand T_VARIABLE { $$ = $2; $$->attr = ZEND_BIND_REF; } 1313 ; 1314 1315 function_call: 1316 name argument_list 1317 { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); } 1318 | T_READONLY argument_list { 1319 zval zv; 1320 if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } 1321 $$ = zend_ast_create(ZEND_AST_CALL, zend_ast_create_zval(&zv), $2); 1322 } 1323 | class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list 1324 { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } 1325 | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list 1326 { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); } 1327 | callable_expr { $<num>$ = CG(zend_lineno); } argument_list { 1328 $$ = zend_ast_create(ZEND_AST_CALL, $1, $3); 1329 $$->lineno = $<num>2; 1330 } 1331 ; 1332 1333 class_name: 1334 T_STATIC 1335 { zval zv; ZVAL_INTERNED_STR(&zv, ZSTR_KNOWN(ZEND_STR_STATIC)); 1336 $$ = zend_ast_create_zval_ex(&zv, ZEND_NAME_NOT_FQ); } 1337 | name { $$ = $1; } 1338 ; 1339 1340 class_name_reference: 1341 class_name { $$ = $1; } 1342 | new_variable { $$ = $1; } 1343 | '(' expr ')' { $$ = $2; } 1344 ; 1345 1346 exit_expr: 1347 %empty { $$ = NULL; } 1348 | '(' optional_expr ')' { $$ = $2; } 1349 ; 1350 1351 backticks_expr: 1352 %empty 1353 { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); } 1354 | T_ENCAPSED_AND_WHITESPACE { $$ = $1; } 1355 | encaps_list { $$ = $1; } 1356 ; 1357 1358 1359 ctor_arguments: 1360 %empty { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); } 1361 | argument_list { $$ = $1; } 1362 ; 1363 1364 1365 dereferenceable_scalar: 1366 T_ARRAY '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LONG; } 1367 | '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; } 1368 | T_CONSTANT_ENCAPSED_STRING { $$ = $1; } 1369 | '"' encaps_list '"' { $$ = $2; } 1370 ; 1371 1372 scalar: 1373 T_LNUMBER { $$ = $1; } 1374 | T_DNUMBER { $$ = $1; } 1375 | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; } 1376 | T_START_HEREDOC T_END_HEREDOC 1377 { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); } 1378 | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; } 1379 | dereferenceable_scalar { $$ = $1; } 1380 | constant { $$ = $1; } 1381 | class_constant { $$ = $1; } 1382 ; 1383 1384 constant: 1385 name { $$ = zend_ast_create(ZEND_AST_CONST, $1); } 1386 | T_LINE { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_LINE); } 1387 | T_FILE { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FILE); } 1388 | T_DIR { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_DIR); } 1389 | T_TRAIT_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_TRAIT_C); } 1390 | T_METHOD_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_METHOD_C); } 1391 | T_FUNC_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FUNC_C); } 1392 | T_NS_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_NS_C); } 1393 | T_CLASS_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_CLASS_C); } 1394 ; 1395 1396 class_constant: 1397 class_name T_PAAMAYIM_NEKUDOTAYIM identifier 1398 { $$ = zend_ast_create_class_const_or_name($1, $3); } 1399 | variable_class_name T_PAAMAYIM_NEKUDOTAYIM identifier 1400 { $$ = zend_ast_create_class_const_or_name($1, $3); } 1401 | class_name T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' 1402 { $$ = zend_ast_create(ZEND_AST_CLASS_CONST, $1, $4); } 1403 | variable_class_name T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' 1404 { $$ = zend_ast_create(ZEND_AST_CLASS_CONST, $1, $4); } 1405 ; 1406 1407 optional_expr: 1408 %empty { $$ = NULL; } 1409 | expr { $$ = $1; } 1410 ; 1411 1412 variable_class_name: 1413 fully_dereferenceable { $$ = $1; } 1414 ; 1415 1416 fully_dereferenceable: 1417 variable { $$ = $1; } 1418 | '(' expr ')' { $$ = $2; } 1419 | dereferenceable_scalar { $$ = $1; } 1420 | class_constant { $$ = $1; } 1421 ; 1422 1423 array_object_dereferenceable: 1424 fully_dereferenceable { $$ = $1; } 1425 | constant { $$ = $1; } 1426 ; 1427 1428 callable_expr: 1429 callable_variable { $$ = $1; } 1430 | '(' expr ')' { $$ = $2; } 1431 | dereferenceable_scalar { $$ = $1; } 1432 ; 1433 1434 callable_variable: 1435 simple_variable 1436 { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1437 | array_object_dereferenceable '[' optional_expr ']' 1438 { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); } 1439 | array_object_dereferenceable '{' expr '}' 1440 { $$ = zend_ast_create_ex(ZEND_AST_DIM, ZEND_DIM_ALTERNATIVE_SYNTAX, $1, $3); } 1441 | array_object_dereferenceable T_OBJECT_OPERATOR property_name argument_list 1442 { $$ = zend_ast_create(ZEND_AST_METHOD_CALL, $1, $3, $4); } 1443 | array_object_dereferenceable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list 1444 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_METHOD_CALL, $1, $3, $4); } 1445 | function_call { $$ = $1; } 1446 ; 1447 1448 variable: 1449 callable_variable 1450 { $$ = $1; } 1451 | static_member 1452 { $$ = $1; } 1453 | array_object_dereferenceable T_OBJECT_OPERATOR property_name 1454 { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); } 1455 | array_object_dereferenceable T_NULLSAFE_OBJECT_OPERATOR property_name 1456 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_PROP, $1, $3); } 1457 ; 1458 1459 simple_variable: 1460 T_VARIABLE { $$ = $1; } 1461 | '$' '{' expr '}' { $$ = $3; } 1462 | '$' simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $2); } 1463 ; 1464 1465 static_member: 1466 class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable 1467 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1468 | variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable 1469 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1470 ; 1471 1472 new_variable: 1473 simple_variable 1474 { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1475 | new_variable '[' optional_expr ']' 1476 { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); } 1477 | new_variable '{' expr '}' 1478 { $$ = zend_ast_create_ex(ZEND_AST_DIM, ZEND_DIM_ALTERNATIVE_SYNTAX, $1, $3); } 1479 | new_variable T_OBJECT_OPERATOR property_name 1480 { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); } 1481 | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name 1482 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_PROP, $1, $3); } 1483 | class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable 1484 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1485 | new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable 1486 { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); } 1487 ; 1488 1489 member_name: 1490 identifier { $$ = $1; } 1491 | '{' expr '}' { $$ = $2; } 1492 | simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1493 ; 1494 1495 property_name: 1496 T_STRING { $$ = $1; } 1497 | '{' expr '}' { $$ = $2; } 1498 | simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1499 ; 1500 1501 array_pair_list: 1502 non_empty_array_pair_list 1503 { /* allow single trailing comma */ $$ = zend_ast_list_rtrim($1); } 1504 ; 1505 1506 possible_array_pair: 1507 %empty { $$ = NULL; } 1508 | array_pair { $$ = $1; } 1509 ; 1510 1511 non_empty_array_pair_list: 1512 non_empty_array_pair_list ',' possible_array_pair 1513 { $$ = zend_ast_list_add($1, $3); } 1514 | possible_array_pair 1515 { $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, $1); } 1516 ; 1517 1518 array_pair: 1519 expr T_DOUBLE_ARROW expr 1520 { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); } 1521 | expr 1522 { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $1, NULL); } 1523 | expr T_DOUBLE_ARROW ampersand variable 1524 { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $4, $1); } 1525 | ampersand variable 1526 { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $2, NULL); } 1527 | T_ELLIPSIS expr 1528 { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); } 1529 | expr T_DOUBLE_ARROW T_LIST '(' array_pair_list ')' 1530 { $5->attr = ZEND_ARRAY_SYNTAX_LIST; 1531 $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); } 1532 | T_LIST '(' array_pair_list ')' 1533 { $3->attr = ZEND_ARRAY_SYNTAX_LIST; 1534 $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, NULL); } 1535 ; 1536 1537 encaps_list: 1538 encaps_list encaps_var 1539 { $$ = zend_ast_list_add($1, $2); } 1540 | encaps_list T_ENCAPSED_AND_WHITESPACE 1541 { $$ = zend_ast_list_add($1, $2); } 1542 | encaps_var 1543 { $$ = zend_ast_create_list(1, ZEND_AST_ENCAPS_LIST, $1); } 1544 | T_ENCAPSED_AND_WHITESPACE encaps_var 1545 { $$ = zend_ast_create_list(2, ZEND_AST_ENCAPS_LIST, $1, $2); } 1546 ; 1547 1548 encaps_var: 1549 T_VARIABLE 1550 { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1551 | T_VARIABLE '[' encaps_var_offset ']' 1552 { $$ = zend_ast_create(ZEND_AST_DIM, 1553 zend_ast_create(ZEND_AST_VAR, $1), $3); } 1554 | T_VARIABLE T_OBJECT_OPERATOR T_STRING 1555 { $$ = zend_ast_create(ZEND_AST_PROP, 1556 zend_ast_create(ZEND_AST_VAR, $1), $3); } 1557 | T_VARIABLE T_NULLSAFE_OBJECT_OPERATOR T_STRING 1558 { $$ = zend_ast_create(ZEND_AST_NULLSAFE_PROP, 1559 zend_ast_create(ZEND_AST_VAR, $1), $3); } 1560 | T_DOLLAR_OPEN_CURLY_BRACES expr '}' 1561 { $$ = zend_ast_create_ex(ZEND_AST_VAR, ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR, $2); } 1562 | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' 1563 { $$ = zend_ast_create_ex(ZEND_AST_VAR, ZEND_ENCAPS_VAR_DOLLAR_CURLY, $2); } 1564 | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' 1565 { $$ = zend_ast_create_ex(ZEND_AST_DIM, ZEND_ENCAPS_VAR_DOLLAR_CURLY, 1566 zend_ast_create(ZEND_AST_VAR, $2), $4); } 1567 | T_CURLY_OPEN variable '}' { $$ = $2; } 1568 ; 1569 1570 encaps_var_offset: 1571 T_STRING { $$ = $1; } 1572 | T_NUM_STRING { $$ = $1; } 1573 | '-' T_NUM_STRING { $$ = zend_negate_num_string($2); } 1574 | T_VARIABLE { $$ = zend_ast_create(ZEND_AST_VAR, $1); } 1575 ; 1576 1577 1578 internal_functions_in_yacc: 1579 T_ISSET '(' isset_variables possible_comma ')' { $$ = $3; } 1580 | T_EMPTY '(' expr ')' { $$ = zend_ast_create(ZEND_AST_EMPTY, $3); } 1581 | T_INCLUDE expr 1582 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2); } 1583 | T_INCLUDE_ONCE expr 1584 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2); } 1585 | T_EVAL '(' expr ')' 1586 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, $3); } 1587 | T_REQUIRE expr 1588 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2); } 1589 | T_REQUIRE_ONCE expr 1590 { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2); } 1591 ; 1592 1593 isset_variables: 1594 isset_variable { $$ = $1; } 1595 | isset_variables ',' isset_variable 1596 { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); } 1597 ; 1598 1599 isset_variable: 1600 expr { $$ = zend_ast_create(ZEND_AST_ISSET, $1); } 1601 ; 1602 1603 %% 1604 1605 /* Over-ride Bison formatting routine to give better token descriptions. 1606 Copy to YYRES the contents of YYSTR for use in yyerror. 1607 YYSTR is taken from yytname, from the %token declaration. 1608 If YYRES is null, do not copy; instead, return the length of what 1609 the result would have been. */ 1610 static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) 1611 { 1612 const char *toktype = yystr; 1613 size_t toktype_len = strlen(toktype); 1614 1615 /* CG(parse_error) states: 1616 * 0 => yyres = NULL, yystr is the unexpected token 1617 * 1 => yyres = NULL, yystr is one of the expected tokens 1618 * 2 => yyres != NULL, yystr is the unexpected token 1619 * 3 => yyres != NULL, yystr is one of the expected tokens 1620 */ 1621 if (yyres && CG(parse_error) < 2) { 1622 CG(parse_error) = 2; 1623 } 1624 1625 if (CG(parse_error) % 2 == 0) { 1626 /* The unexpected token */ 1627 char buffer[120]; 1628 const unsigned char *tokcontent, *tokcontent_end; 1629 size_t tokcontent_len; 1630 1631 CG(parse_error)++; 1632 1633 if (LANG_SCNG(yy_text)[0] == 0 && 1634 LANG_SCNG(yy_leng) == 1 && 1635 strcmp(toktype, "\"end of file\"") == 0) { 1636 if (yyres) { 1637 yystpcpy(yyres, "end of file"); 1638 } 1639 return sizeof("end of file")-1; 1640 } 1641 1642 /* Prevent the backslash getting doubled in the output (eugh) */ 1643 if (strcmp(toktype, "\"'\\\\'\"") == 0) { 1644 if (yyres) { 1645 yystpcpy(yyres, "token \"\\\""); 1646 } 1647 return sizeof("token \"\\\"")-1; 1648 } 1649 1650 /* We used "amp" as a dummy label to avoid a duplicate token literal warning. */ 1651 if (strcmp(toktype, "\"amp\"") == 0) { 1652 if (yyres) { 1653 yystpcpy(yyres, "token \"&\""); 1654 } 1655 return sizeof("token \"&\"")-1; 1656 } 1657 1658 /* Avoid unreadable """ */ 1659 /* "'" would theoretically be just as bad, but is never currently parsed as a separate token */ 1660 if (strcmp(toktype, "'\"'") == 0) { 1661 if (yyres) { 1662 yystpcpy(yyres, "double-quote mark"); 1663 } 1664 return sizeof("double-quote mark")-1; 1665 } 1666 1667 /* Strip off the outer quote marks */ 1668 if (toktype_len >= 2 && *toktype == '"') { 1669 toktype++; 1670 toktype_len -= 2; 1671 } 1672 1673 /* If the token always has one form, the %token line should have a single-quoted name */ 1674 /* The parser rules also include single-character un-named tokens which will be single-quoted here */ 1675 /* We re-format this with double quotes here to ensure everything's consistent */ 1676 if (toktype_len > 0 && *toktype == '\'') { 1677 if (yyres) { 1678 snprintf(buffer, sizeof(buffer), "token \"%.*s\"", (int)toktype_len-2, toktype+1); 1679 yystpcpy(yyres, buffer); 1680 } 1681 return toktype_len + sizeof("token ")-1; 1682 } 1683 1684 /* Fetch the content of the last seen token from global lexer state */ 1685 tokcontent = LANG_SCNG(yy_text); 1686 tokcontent_len = LANG_SCNG(yy_leng); 1687 1688 /* For T_BAD_CHARACTER, the content probably won't be a printable char */ 1689 /* Also, "unexpected invalid character" sounds a bit redundant */ 1690 if (tokcontent_len == 1 && strcmp(yystr, "\"invalid character\"") == 0) { 1691 if (yyres) { 1692 snprintf(buffer, sizeof(buffer), "character 0x%02hhX", *tokcontent); 1693 yystpcpy(yyres, buffer); 1694 } 1695 return sizeof("character 0x00")-1; 1696 } 1697 1698 /* Truncate at line end to avoid messing up log formats */ 1699 tokcontent_end = memchr(tokcontent, '\n', tokcontent_len); 1700 if (tokcontent_end != NULL) { 1701 tokcontent_len = (tokcontent_end - tokcontent); 1702 } 1703 1704 /* Try to be helpful about what kind of string was found, before stripping the quotes */ 1705 if (tokcontent_len > 0 && strcmp(yystr, "\"quoted string\"") == 0) { 1706 if (*tokcontent == '"') { 1707 toktype = "double-quoted string"; 1708 toktype_len = sizeof("double-quoted string")-1; 1709 } 1710 else if (*tokcontent == '\'') { 1711 toktype = "single-quoted string"; 1712 toktype_len = sizeof("single-quoted string")-1; 1713 } 1714 } 1715 1716 /* For quoted strings, strip off another layer of quotes to avoid putting quotes inside quotes */ 1717 if (tokcontent_len > 0 && (*tokcontent == '\'' || *tokcontent=='"')) { 1718 tokcontent++; 1719 tokcontent_len--; 1720 } 1721 if (tokcontent_len > 0 && (tokcontent[tokcontent_len-1] == '\'' || tokcontent[tokcontent_len-1] == '"')) { 1722 tokcontent_len--; 1723 } 1724 1725 /* Truncate to 30 characters and add a ... */ 1726 if (tokcontent_len > 30 + sizeof("...")-1) { 1727 if (yyres) { 1728 snprintf(buffer, sizeof(buffer), "%.*s \"%.*s...\"", (int)toktype_len, toktype, 30, tokcontent); 1729 yystpcpy(yyres, buffer); 1730 } 1731 return toktype_len + 30 + sizeof(" \"...\"")-1; 1732 } 1733 1734 if (yyres) { 1735 snprintf(buffer, sizeof(buffer), "%.*s \"%.*s\"", (int)toktype_len, toktype, (int)tokcontent_len, tokcontent); 1736 yystpcpy(yyres, buffer); 1737 } 1738 return toktype_len + tokcontent_len + sizeof(" \"\"")-1; 1739 } 1740 1741 /* One of the expected tokens */ 1742 1743 /* Prevent the backslash getting doubled in the output (eugh) */ 1744 if (strcmp(toktype, "\"'\\\\'\"") == 0) { 1745 if (yyres) { 1746 yystpcpy(yyres, "\"\\\""); 1747 } 1748 return sizeof("\"\\\"")-1; 1749 } 1750 1751 /* Strip off the outer quote marks */ 1752 if (toktype_len >= 2 && *toktype == '"') { 1753 toktype++; 1754 toktype_len -= 2; 1755 } 1756 1757 if (yyres) { 1758 YYSIZE_T yyn = 0; 1759 1760 for (; yyn < toktype_len; ++yyn) { 1761 /* Replace single quotes with double for consistency */ 1762 if (toktype[yyn] == '\'') { 1763 yyres[yyn] = '"'; 1764 } 1765 else { 1766 yyres[yyn] = toktype[yyn]; 1767 } 1768 } 1769 yyres[toktype_len] = '\0'; 1770 } 1771 1772 return toktype_len; 1773 } 1774