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