php-parser/grammar/parser.template000064400000004421150250175720013311 0ustar00semValue #semval($,%t) $this->semValue #semval(%n) $stackPos-(%l-%n) #semval(%n,%t) $stackPos-(%l-%n) namespace PhpParser\Parser; use PhpParser\Error; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Name; use PhpParser\Node\Scalar; use PhpParser\Node\Stmt; #include; /* This is an automatically GENERATED file, which should not be manually edited. * Instead edit one of the following: * * the grammar files grammar/php5.y or grammar/php7.y * * the skeleton file grammar/parser.template * * the preprocessing script grammar/rebuildParsers.php */ class #(-p) extends \PhpParser\ParserAbstract { protected $tokenToSymbolMapSize = #(YYMAXLEX); protected $actionTableSize = #(YYLAST); protected $gotoTableSize = #(YYGLAST); protected $invalidSymbol = #(YYBADCH); protected $errorSymbol = #(YYINTERRTOK); protected $defaultAction = #(YYDEFAULT); protected $unexpectedTokenRule = #(YYUNEXPECTED); protected $YY2TBLSTATE = #(YY2TBLSTATE); protected $numNonLeafStates = #(YYNLSTATES); protected $symbolToName = array( #listvar terminals ); protected $tokenToSymbol = array( #listvar yytranslate ); protected $action = array( #listvar yyaction ); protected $actionCheck = array( #listvar yycheck ); protected $actionBase = array( #listvar yybase ); protected $actionDefault = array( #listvar yydefault ); protected $goto = array( #listvar yygoto ); protected $gotoCheck = array( #listvar yygcheck ); protected $gotoBase = array( #listvar yygbase ); protected $gotoDefault = array( #listvar yygdefault ); protected $ruleToNonTerminal = array( #listvar yylhs ); protected $ruleToLength = array( #listvar yylen ); #if -t protected $productions = array( #production-strings; ); #endif protected function initReduceCallbacks() { $this->reduceCallbacks = [ #reduce %n => function ($stackPos) { %b }, #noact %n => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, #endreduce ]; } } #tailcode; php-parser/grammar/php5.y000064400000144303150250175720011332 0ustar00%pure_parser %expect 6 %tokens %% start: top_statement_list { $$ = $this->handleNamespaces($1); } ; top_statement_list_ex: top_statement_list_ex top_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; top_statement_list: top_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; ampersand: T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG ; reserved_non_modifiers: T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN | T_MATCH ; semi_reserved: reserved_non_modifiers | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC ; identifier_ex: T_STRING { $$ = Node\Identifier[$1]; } | semi_reserved { $$ = Node\Identifier[$1]; } ; identifier: T_STRING { $$ = Node\Identifier[$1]; } ; reserved_non_modifiers_identifier: reserved_non_modifiers { $$ = Node\Identifier[$1]; } ; namespace_name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } ; legacy_namespace_name: namespace_name { $$ = $1; } | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } ; plain_variable: T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } ; top_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } | T_NAMESPACE namespace_name ';' { $$ = Stmt\Namespace_[$2, null]; $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($$); } | T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } | T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; } | group_use_declaration ';' { $$ = $1; } | T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; } ; use_type: T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } ; group_use_declaration: T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' { $$ = Stmt\GroupUse[$3, $6, $2]; } | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } ; unprefixed_use_declarations: unprefixed_use_declarations ',' unprefixed_use_declaration { push($1, $3); } | unprefixed_use_declaration { init($1); } ; use_declarations: use_declarations ',' use_declaration { push($1, $3); } | use_declaration { init($1); } ; inline_use_declarations: inline_use_declarations ',' inline_use_declaration { push($1, $3); } | inline_use_declaration { init($1); } ; unprefixed_use_declaration: namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | namespace_name T_AS identifier { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; use_declaration: legacy_namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | legacy_namespace_name T_AS identifier { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; inline_use_declaration: unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } ; constant_declaration_list: constant_declaration_list ',' constant_declaration { push($1, $3); } | constant_declaration { init($1); } ; constant_declaration: identifier '=' static_scalar { $$ = Node\Const_[$1, $3]; } ; class_const_list: class_const_list ',' class_const { push($1, $3); } | class_const { init($1); } ; class_const: identifier_ex '=' static_scalar { $$ = Node\Const_[$1, $3]; } ; inner_statement_list_ex: inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; inner_statement_list: inner_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; inner_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } ; non_empty_statement: '{' inner_statement_list '}' { if ($2) { $$ = $2; prependLeadingComments($$); } else { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if (null === $$) { $$ = array(); } } } | T_IF parentheses_expr statement elseif_list else_single { $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; } | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; } | T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; } | T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; } | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } | T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; } | T_BREAK ';' { $$ = Stmt\Break_[null]; } | T_BREAK expr ';' { $$ = Stmt\Break_[$2]; } | T_CONTINUE ';' { $$ = Stmt\Continue_[null]; } | T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; } | T_RETURN ';' { $$ = Stmt\Return_[null]; } | T_RETURN expr ';' { $$ = Stmt\Return_[$2]; } | T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; } | T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; } | T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; } | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } | yield_expr ';' { $$ = Stmt\Expression[$1]; } | expr ';' { $$ = Stmt\Expression[$1]; } | T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; } | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } | T_TRY '{' inner_statement_list '}' catches optional_finally { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } | T_THROW expr ';' { $$ = Stmt\Throw_[$2]; } | T_GOTO identifier ';' { $$ = Stmt\Goto_[$2]; } | identifier ':' { $$ = Stmt\Label[$1]; } | expr error { $$ = Stmt\Expression[$1]; } | error { $$ = array(); /* means: no statement */ } ; statement: non_empty_statement { $$ = $1; } | ';' { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if ($$ === null) $$ = array(); /* means: no statement */ } ; catches: /* empty */ { init(); } | catches catch { push($1, $2); } ; catch: T_CATCH '(' name plain_variable ')' '{' inner_statement_list '}' { $$ = Stmt\Catch_[array($3), $4, $7]; } ; optional_finally: /* empty */ { $$ = null; } | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } ; variables_list: variable { init($1); } | variables_list ',' variable { push($1, $3); } ; optional_ref: /* empty */ { $$ = false; } | ampersand { $$ = true; } ; optional_arg_ref: /* empty */ { $$ = false; } | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; } ; optional_ellipsis: /* empty */ { $$ = false; } | T_ELLIPSIS { $$ = true; } ; identifier_maybe_readonly: identifier { $$ = $1; } | T_READONLY { $$ = Node\Identifier[$1]; } ; function_declaration_statement: T_FUNCTION optional_ref identifier_maybe_readonly '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } ; class_declaration_statement: class_entry_type identifier extends_from implements_list '{' class_statement_list '}' { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; $this->checkClass($$, #2); } | T_INTERFACE identifier interface_extends_list '{' class_statement_list '}' { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; $this->checkInterface($$, #2); } | T_TRAIT identifier '{' class_statement_list '}' { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; } ; class_entry_type: T_CLASS { $$ = 0; } | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } ; extends_from: /* empty */ { $$ = null; } | T_EXTENDS class_name { $$ = $2; } ; interface_extends_list: /* empty */ { $$ = array(); } | T_EXTENDS class_name_list { $$ = $2; } ; implements_list: /* empty */ { $$ = array(); } | T_IMPLEMENTS class_name_list { $$ = $2; } ; class_name_list: class_name { init($1); } | class_name_list ',' class_name { push($1, $3); } ; for_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } ; foreach_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } ; declare_statement: non_empty_statement { $$ = toArray($1); } | ';' { $$ = null; } | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } ; declare_list: declare_list_element { init($1); } | declare_list ',' declare_list_element { push($1, $3); } ; declare_list_element: identifier '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; } ; switch_case_list: '{' case_list '}' { $$ = $2; } | '{' ';' case_list '}' { $$ = $3; } | ':' case_list T_ENDSWITCH ';' { $$ = $2; } | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } ; case_list: /* empty */ { init(); } | case_list case { push($1, $2); } ; case: T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } ; case_separator: ':' | ';' ; while_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } ; elseif_list: /* empty */ { init(); } | elseif_list elseif { push($1, $2); } ; elseif: T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; } ; new_elseif_list: /* empty */ { init(); } | new_elseif_list new_elseif { push($1, $2); } ; new_elseif: T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; } ; else_single: /* empty */ { $$ = null; } | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } ; new_else_single: /* empty */ { $$ = null; } | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } ; foreach_variable: variable { $$ = array($1, false); } | ampersand variable { $$ = array($2, true); } | list_expr { $$ = array($1, false); } ; parameter_list: non_empty_parameter_list { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_parameter_list: parameter { init($1); } | non_empty_parameter_list ',' parameter { push($1, $3); } ; parameter: optional_param_type optional_arg_ref optional_ellipsis plain_variable { $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); } | optional_param_type optional_arg_ref optional_ellipsis plain_variable '=' static_scalar { $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); } ; type: name { $$ = $1; } | T_ARRAY { $$ = Node\Identifier['array']; } | T_CALLABLE { $$ = Node\Identifier['callable']; } ; optional_param_type: /* empty */ { $$ = null; } | type { $$ = $1; } ; optional_return_type: /* empty */ { $$ = null; } | ':' type { $$ = $2; } ; argument_list: '(' ')' { $$ = array(); } | '(' non_empty_argument_list ')' { $$ = $2; } | '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); } ; non_empty_argument_list: argument { init($1); } | non_empty_argument_list ',' argument { push($1, $3); } ; argument: expr { $$ = Node\Arg[$1, false, false]; } | ampersand variable { $$ = Node\Arg[$2, true, false]; } | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } ; global_var_list: global_var_list ',' global_var { push($1, $3); } | global_var { init($1); } ; global_var: plain_variable { $$ = $1; } | '$' variable { $$ = Expr\Variable[$2]; } | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } ; static_var_list: static_var_list ',' static_var { push($1, $3); } | static_var { init($1); } ; static_var: plain_variable { $$ = Stmt\StaticVar[$1, null]; } | plain_variable '=' static_scalar { $$ = Stmt\StaticVar[$1, $3]; } ; class_statement_list_ex: class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } | /* empty */ { init(); } ; class_statement_list: class_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; class_statement: variable_modifiers property_declaration_list ';' { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); } | T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2, 0]; } | method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; $this->checkClassMethod($$, #1); } | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } ; trait_adaptations: ';' { $$ = array(); } | '{' trait_adaptation_list '}' { $$ = $2; } ; trait_adaptation_list: /* empty */ { init(); } | trait_adaptation_list trait_adaptation { push($1, $2); } ; trait_adaptation: trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } | trait_method_reference T_AS member_modifier identifier_ex ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } | trait_method_reference T_AS member_modifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } | trait_method_reference T_AS identifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } | trait_method_reference T_AS reserved_non_modifiers_identifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } ; trait_method_reference_fully_qualified: name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = array($1, $3); } ; trait_method_reference: trait_method_reference_fully_qualified { $$ = $1; } | identifier_ex { $$ = array(null, $1); } ; method_body: ';' /* abstract method */ { $$ = null; } | '{' inner_statement_list '}' { $$ = $2; } ; variable_modifiers: non_empty_member_modifiers { $$ = $1; } | T_VAR { $$ = 0; } ; method_modifiers: /* empty */ { $$ = 0; } | non_empty_member_modifiers { $$ = $1; } ; non_empty_member_modifiers: member_modifier { $$ = $1; } | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } ; member_modifier: T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } ; property_declaration_list: property_declaration { init($1); } | property_declaration_list ',' property_declaration { push($1, $3); } ; property_decl_name: T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } ; property_declaration: property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } | property_decl_name '=' static_scalar { $$ = Stmt\PropertyProperty[$1, $3]; } ; expr_list: expr_list ',' expr { push($1, $3); } | expr { init($1); } ; for_expr: /* empty */ { $$ = array(); } | expr_list { $$ = $1; } ; expr: variable { $$ = $1; } | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; } | variable '=' ampersand new_expr { $$ = Expr\AssignRef[$1, $4]; } | new_expr { $$ = $1; } | T_CLONE expr { $$ = Expr\Clone_[$2]; } | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } | variable T_INC { $$ = Expr\PostInc[$1]; } | T_INC variable { $$ = Expr\PreInc [$2]; } | variable T_DEC { $$ = Expr\PostDec[$1]; } | T_DEC variable { $$ = Expr\PreDec [$2]; } | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' expr { $$ = Expr\BooleanNot[$2]; } | '~' expr { $$ = Expr\BitwiseNot[$2]; } | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } | parentheses_expr { $$ = $1; } /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */ | '(' new_expr ')' { $$ = $2; } | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } | T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; } | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } | T_DOUBLE_CAST expr { $attrs = attributes(); $attrs['kind'] = $this->getFloatCastKind($1); $$ = new Expr\Cast\Double($2, $attrs); } | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } | T_EXIT exit_expr { $attrs = attributes(); $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; $$ = new Expr\Exit_($2, $attrs); } | '@' expr { $$ = Expr\ErrorSuppress[$2]; } | scalar { $$ = $1; } | array_expr { $$ = $1; } | scalar_dereference { $$ = $1; } | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } | T_PRINT expr { $$ = Expr\Print_[$2]; } | T_YIELD { $$ = Expr\Yield_[null, null]; } | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type '{' inner_statement_list '}' { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type '{' inner_statement_list '}' { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } ; parentheses_expr: '(' expr ')' { $$ = $2; } | '(' yield_expr ')' { $$ = $2; } ; yield_expr: T_YIELD expr { $$ = Expr\Yield_[$2, null]; } | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } ; array_expr: T_ARRAY '(' array_pair_list ')' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; $$ = new Expr\Array_($3, $attrs); } | '[' array_pair_list ']' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; $$ = new Expr\Array_($2, $attrs); } ; scalar_dereference: array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[Scalar\String_::fromString($1, attributes()), $3]; } | constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; anonymous_class: T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); $this->checkClass($$[0], -1); } ; new_expr: T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } | T_NEW anonymous_class { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } ; lexical_vars: /* empty */ { $$ = array(); } | T_USE '(' lexical_var_list ')' { $$ = $3; } ; lexical_var_list: lexical_var { init($1); } | lexical_var_list ',' lexical_var { push($1, $3); } ; lexical_var: optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } ; name_readonly: T_READONLY { $$ = Name[$1]; } ; function_call: name argument_list { $$ = Expr\FuncCall[$1, $2]; } | name_readonly argument_list { $$ = Expr\FuncCall[$1, $2]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex argument_list { $$ = Expr\StaticCall[$1, $3, $4]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list { $$ = Expr\StaticCall[$1, $4, $6]; } | static_property argument_list { $$ = $this->fixupPhp5StaticPropCall($1, $2, attributes()); } | variable_without_objects argument_list { $$ = Expr\FuncCall[$1, $2]; } | function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; class_name: T_STATIC { $$ = Name[$1]; } | name { $$ = $1; } ; name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } ; class_name_reference: class_name { $$ = $1; } | dynamic_class_name_reference { $$ = $1; } ; dynamic_class_name_reference: object_access_for_dcnr { $$ = $1; } | base_variable { $$ = $1; } ; class_name_or_var: class_name { $$ = $1; } | reference_variable { $$ = $1; } ; object_access_for_dcnr: base_variable T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | object_access_for_dcnr T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; exit_expr: /* empty */ { $$ = null; } | '(' ')' { $$ = null; } | parentheses_expr { $$ = $1; } ; backticks_expr: /* empty */ { $$ = array(); } | T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); } | encaps_list { parseEncapsed($1, '`', false); $$ = $1; } ; ctor_arguments: /* empty */ { $$ = array(); } | argument_list { $$ = $1; } ; common_scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } | T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes(), false); } | T_LINE { $$ = Scalar\MagicConst\Line[]; } | T_FILE { $$ = Scalar\MagicConst\File[]; } | T_DIR { $$ = Scalar\MagicConst\Dir[]; } | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), false); } | T_START_HEREDOC T_END_HEREDOC { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), false); } ; static_scalar: common_scalar { $$ = $1; } | class_name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } | name { $$ = Expr\ConstFetch[$1]; } | T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; } | '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; } | static_operation { $$ = $1; } ; static_operation: static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | static_scalar T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG static_scalar { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | static_scalar T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG static_scalar { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; } | static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; } | static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; } | static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; } | static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; } | static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; } | static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' static_scalar { $$ = Expr\BooleanNot[$2]; } | '~' static_scalar { $$ = Expr\BitwiseNot[$2]; } | static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; } | static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; } | static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; } | static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; } | static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; } | static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | '(' static_scalar ')' { $$ = $2; } ; constant: name { $$ = Expr\ConstFetch[$1]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } ; scalar: common_scalar { $$ = $1; } | constant { $$ = $1; } | '"' encaps_list '"' { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } ; static_array_pair_list: /* empty */ { $$ = array(); } | non_empty_static_array_pair_list optional_comma { $$ = $1; } ; optional_comma: /* empty */ | ',' ; non_empty_static_array_pair_list: non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); } | static_array_pair { init($1); } ; static_array_pair: static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; } | static_scalar { $$ = Expr\ArrayItem[$1, null, false]; } ; variable: object_access { $$ = $1; } | base_variable { $$ = $1; } | function_call { $$ = $1; } | new_expr_array_deref { $$ = $1; } ; new_expr_array_deref: '(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; } | new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; object_access: variable_or_new_expr T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list { $$ = Expr\MethodCall[$1, $3, $4]; } | object_access argument_list { $$ = Expr\FuncCall[$1, $2]; } | object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; variable_or_new_expr: variable { $$ = $1; } | '(' new_expr ')' { $$ = $2; } ; variable_without_objects: reference_variable { $$ = $1; } | '$' variable_without_objects { $$ = Expr\Variable[$2]; } ; base_variable: variable_without_objects { $$ = $1; } | static_property { $$ = $1; } ; static_property: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable { $$ = Expr\StaticPropertyFetch[$1, $4]; } | static_property_with_arrays { $$ = $1; } ; static_property_simple_name: T_VARIABLE { $var = parseVar($1); $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } ; static_property_with_arrays: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_property_simple_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}' { $$ = Expr\StaticPropertyFetch[$1, $5]; } | static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; reference_variable: reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } | plain_variable { $$ = $1; } | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } ; dim_offset: /* empty */ { $$ = null; } | expr { $$ = $1; } ; object_property: identifier { $$ = $1; } | '{' expr '}' { $$ = $2; } | variable_without_objects { $$ = $1; } | error { $$ = Expr\Error[]; $this->errorState = 2; } ; list_expr: T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } ; list_expr_elements: list_expr_elements ',' list_expr_element { push($1, $3); } | list_expr_element { init($1); } ; list_expr_element: variable { $$ = Expr\ArrayItem[$1, null, false]; } | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } | /* empty */ { $$ = null; } ; array_pair_list: /* empty */ { $$ = array(); } | non_empty_array_pair_list optional_comma { $$ = $1; } ; non_empty_array_pair_list: non_empty_array_pair_list ',' array_pair { push($1, $3); } | array_pair { init($1); } ; array_pair: expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } | expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } ; encaps_list: encaps_list encaps_var { push($1, $2); } | encaps_list encaps_string_part { push($1, $2); } | encaps_var { init($1); } | encaps_string_part encaps_var { init($1, $2); } ; encaps_string_part: T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } ; encaps_str_varname: T_STRING_VARNAME { $$ = Expr\Variable[$1]; } ; encaps_var: plain_variable { $$ = $1; } | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; } | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' { $$ = Expr\ArrayDimFetch[$2, $4]; } | T_CURLY_OPEN variable '}' { $$ = $2; } ; encaps_var_offset: T_STRING { $$ = Scalar\String_[$1]; } | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } | plain_variable { $$ = $1; } ; %% php-parser/grammar/tokens.template000064400000000452150250175720013320 0ustar00semValue #semval($,%t) $this->semValue #semval(%n) $this->stackPos-(%l-%n) #semval(%n,%t) $this->stackPos-(%l-%n) namespace PhpParser\Parser; #include; /* GENERATED file based on grammar/tokens.y */ final class Tokens { #tokenval const %s = %n; #endtokenval } php-parser/grammar/phpyLang.php000064400000013556150250175720012564 0ustar00\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') (?"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") (?(?&singleQuotedString)|(?&doubleQuotedString)) (?/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/) (?\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) )'; const PARAMS = '\[(?[^[\]]*+(?:\[(?¶ms)\][^[\]]*+)*+)\]'; const ARGS = '\((?[^()]*+(?:\((?&args)\)[^()]*+)*+)\)'; /////////////////////////////// /// Preprocessing functions /// /////////////////////////////// function preprocessGrammar($code) { $code = resolveNodes($code); $code = resolveMacros($code); $code = resolveStackAccess($code); return $code; } function resolveNodes($code) { return preg_replace_callback( '~\b(?[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~', function($matches) { // recurse $matches['params'] = resolveNodes($matches['params']); $params = magicSplit( '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', $matches['params'] ); $paramCode = ''; foreach ($params as $param) { $paramCode .= $param . ', '; } return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())'; }, $code ); } function resolveMacros($code) { return preg_replace_callback( '~\b(?)(?!array\()(?[a-z][A-Za-z]++)' . ARGS . '~', function($matches) { // recurse $matches['args'] = resolveMacros($matches['args']); $name = $matches['name']; $args = magicSplit( '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', $matches['args'] ); if ('attributes' === $name) { assertArgs(0, $args, $name); return '$this->startAttributeStack[#1] + $this->endAttributes'; } if ('stackAttributes' === $name) { assertArgs(1, $args, $name); return '$this->startAttributeStack[' . $args[0] . ']' . ' + $this->endAttributeStack[' . $args[0] . ']'; } if ('init' === $name) { return '$$ = array(' . implode(', ', $args) . ')'; } if ('push' === $name) { assertArgs(2, $args, $name); return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0]; } if ('pushNormalizing' === $name) { assertArgs(2, $args, $name); return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }' . ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }'; } if ('toArray' == $name) { assertArgs(1, $args, $name); return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')'; } if ('parseVar' === $name) { assertArgs(1, $args, $name); return 'substr(' . $args[0] . ', 1)'; } if ('parseEncapsed' === $name) { assertArgs(3, $args, $name); return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {' . ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }'; } if ('makeNop' === $name) { assertArgs(3, $args, $name); return '$startAttributes = ' . $args[1] . ';' . ' if (isset($startAttributes[\'comments\']))' . ' { ' . $args[0] . ' = new Stmt\Nop($startAttributes + ' . $args[2] . '); }' . ' else { ' . $args[0] . ' = null; }'; } if ('makeZeroLengthNop' == $name) { assertArgs(2, $args, $name); return '$startAttributes = ' . $args[1] . ';' . ' if (isset($startAttributes[\'comments\']))' . ' { ' . $args[0] . ' = new Stmt\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); }' . ' else { ' . $args[0] . ' = null; }'; } if ('prependLeadingComments' === $name) { assertArgs(1, $args, $name); return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; ' . 'if (!empty($attrs[\'comments\'])) {' . '$stmts[0]->setAttribute(\'comments\', ' . 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }'; } return $matches[0]; }, $code ); } function assertArgs($num, $args, $name) { if ($num != count($args)) { die('Wrong argument count for ' . $name . '().'); } } function resolveStackAccess($code) { $code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code); $code = preg_replace('/#(\d+)/', '$$1', $code); return $code; } function removeTrailingWhitespace($code) { $lines = explode("\n", $code); $lines = array_map('rtrim', $lines); return implode("\n", $lines); } ////////////////////////////// /// Regex helper functions /// ////////////////////////////// function regex($regex) { return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~'; } function magicSplit($regex, $string) { $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); foreach ($pieces as &$piece) { $piece = trim($piece); } if ($pieces === ['']) { return []; } return $pieces; } php-parser/grammar/README.md000064400000002611150250175720011536 0ustar00What do all those files mean? ============================= * `php5.y`: PHP 5 grammar written in a pseudo language * `php7.y`: PHP 7 grammar written in a pseudo language * `tokens.y`: Tokens definition shared between PHP 5 and PHP 7 grammars * `parser.template`: A `kmyacc` parser prototype file for PHP * `tokens.template`: A `kmyacc` prototype file for the `Tokens` class * `rebuildParsers.php`: Preprocesses the grammar and builds the parser using `kmyacc` .phpy pseudo language ===================== The `.y` file is a normal grammar in `kmyacc` (`yacc`) style, with some transformations applied to it: * Nodes are created using the syntax `Name[..., ...]`. This is transformed into `new Name(..., ..., attributes())` * Some function-like constructs are resolved (see `rebuildParsers.php` for a list) Building the parser =================== Run `php grammar/rebuildParsers.php` to rebuild the parsers. Additional options: * The `KMYACC` environment variable can be used to specify an alternative `kmyacc` binary. By default the `phpyacc` dev dependency will be used. To use the original `kmyacc`, you need to compile [moriyoshi's fork](https://github.com/moriyoshi/kmyacc-forked). * The `--debug` option enables emission of debug symbols and creates the `y.output` file. * The `--keep-tmp-grammar` option preserves the preprocessed grammar file. php-parser/grammar/php7.y000064400000160422150250175720011334 0ustar00%pure_parser %expect 2 %tokens %% start: top_statement_list { $$ = $this->handleNamespaces($1); } ; top_statement_list_ex: top_statement_list_ex top_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; top_statement_list: top_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; ampersand: T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG ; reserved_non_modifiers: T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN | T_MATCH | T_ENUM ; semi_reserved: reserved_non_modifiers | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC | T_READONLY ; identifier_maybe_reserved: T_STRING { $$ = Node\Identifier[$1]; } | semi_reserved { $$ = Node\Identifier[$1]; } ; identifier_not_reserved: T_STRING { $$ = Node\Identifier[$1]; } ; reserved_non_modifiers_identifier: reserved_non_modifiers { $$ = Node\Identifier[$1]; } ; namespace_declaration_name: T_STRING { $$ = Name[$1]; } | semi_reserved { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } ; namespace_name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } ; legacy_namespace_name: namespace_name { $$ = $1; } | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } ; plain_variable: T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } ; semi: ';' { /* nothing */ } | error { /* nothing */ } ; no_comma: /* empty */ { /* nothing */ } | ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); } ; optional_comma: /* empty */ | ',' ; attribute_decl: class_name { $$ = Node\Attribute[$1, []]; } | class_name argument_list { $$ = Node\Attribute[$1, $2]; } ; attribute_group: attribute_decl { init($1); } | attribute_group ',' attribute_decl { push($1, $3); } ; attribute: T_ATTRIBUTE attribute_group optional_comma ']' { $$ = Node\AttributeGroup[$2]; } ; attributes: attribute { init($1); } | attributes attribute { push($1, $2); } ; optional_attributes: /* empty */ { $$ = []; } | attributes { $$ = $1; } ; top_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } | T_NAMESPACE namespace_declaration_name semi { $$ = Stmt\Namespace_[$2, null]; $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($$); } | T_NAMESPACE namespace_declaration_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_USE use_declarations semi { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } | T_USE use_type use_declarations semi { $$ = Stmt\Use_[$3, $2]; } | group_use_declaration semi { $$ = $1; } | T_CONST constant_declaration_list semi { $$ = Stmt\Const_[$2]; } ; use_type: T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } ; group_use_declaration: T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' { $$ = Stmt\GroupUse[$3, $6, $2]; } | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } ; unprefixed_use_declarations: non_empty_unprefixed_use_declarations optional_comma { $$ = $1; } ; non_empty_unprefixed_use_declarations: non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration { push($1, $3); } | unprefixed_use_declaration { init($1); } ; use_declarations: non_empty_use_declarations no_comma { $$ = $1; } ; non_empty_use_declarations: non_empty_use_declarations ',' use_declaration { push($1, $3); } | use_declaration { init($1); } ; inline_use_declarations: non_empty_inline_use_declarations optional_comma { $$ = $1; } ; non_empty_inline_use_declarations: non_empty_inline_use_declarations ',' inline_use_declaration { push($1, $3); } | inline_use_declaration { init($1); } ; unprefixed_use_declaration: namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | namespace_name T_AS identifier_not_reserved { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; use_declaration: legacy_namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | legacy_namespace_name T_AS identifier_not_reserved { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; inline_use_declaration: unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } ; constant_declaration_list: non_empty_constant_declaration_list no_comma { $$ = $1; } ; non_empty_constant_declaration_list: non_empty_constant_declaration_list ',' constant_declaration { push($1, $3); } | constant_declaration { init($1); } ; constant_declaration: identifier_not_reserved '=' expr { $$ = Node\Const_[$1, $3]; } ; class_const_list: non_empty_class_const_list no_comma { $$ = $1; } ; non_empty_class_const_list: non_empty_class_const_list ',' class_const { push($1, $3); } | class_const { init($1); } ; class_const: identifier_maybe_reserved '=' expr { $$ = Node\Const_[$1, $3]; } ; inner_statement_list_ex: inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; inner_statement_list: inner_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; inner_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } ; non_empty_statement: '{' inner_statement_list '}' { if ($2) { $$ = $2; prependLeadingComments($$); } else { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if (null === $$) { $$ = array(); } } } | T_IF '(' expr ')' statement elseif_list else_single { $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; } | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; } | T_WHILE '(' expr ')' while_statement { $$ = Stmt\While_[$3, $5]; } | T_DO statement T_WHILE '(' expr ')' ';' { $$ = Stmt\Do_ [$5, toArray($2)]; } | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } | T_SWITCH '(' expr ')' switch_case_list { $$ = Stmt\Switch_[$3, $5]; } | T_BREAK optional_expr semi { $$ = Stmt\Break_[$2]; } | T_CONTINUE optional_expr semi { $$ = Stmt\Continue_[$2]; } | T_RETURN optional_expr semi { $$ = Stmt\Return_[$2]; } | T_GLOBAL global_var_list semi { $$ = Stmt\Global_[$2]; } | T_STATIC static_var_list semi { $$ = Stmt\Static_[$2]; } | T_ECHO expr_list_forbid_comma semi { $$ = Stmt\Echo_[$2]; } | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } | expr semi { $e = $1; if ($e instanceof Expr\Throw_) { // For backwards-compatibility reasons, convert throw in statement position into // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). $$ = Stmt\Throw_[$e->expr]; } else { $$ = Stmt\Expression[$e]; } } | T_UNSET '(' variables_list ')' semi { $$ = Stmt\Unset_[$3]; } | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } | T_FOREACH '(' expr error ')' foreach_statement { $$ = Stmt\Foreach_[$3, new Expr\Error(stackAttributes(#4)), ['stmts' => $6]]; } | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } | T_TRY '{' inner_statement_list '}' catches optional_finally { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } | T_GOTO identifier_not_reserved semi { $$ = Stmt\Goto_[$2]; } | identifier_not_reserved ':' { $$ = Stmt\Label[$1]; } | error { $$ = array(); /* means: no statement */ } ; statement: non_empty_statement { $$ = $1; } | ';' { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if ($$ === null) $$ = array(); /* means: no statement */ } ; catches: /* empty */ { init(); } | catches catch { push($1, $2); } ; name_union: name { init($1); } | name_union '|' name { push($1, $3); } ; catch: T_CATCH '(' name_union optional_plain_variable ')' '{' inner_statement_list '}' { $$ = Stmt\Catch_[$3, $4, $7]; } ; optional_finally: /* empty */ { $$ = null; } | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } ; variables_list: non_empty_variables_list optional_comma { $$ = $1; } ; non_empty_variables_list: variable { init($1); } | non_empty_variables_list ',' variable { push($1, $3); } ; optional_ref: /* empty */ { $$ = false; } | ampersand { $$ = true; } ; optional_arg_ref: /* empty */ { $$ = false; } | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; } ; optional_ellipsis: /* empty */ { $$ = false; } | T_ELLIPSIS { $$ = true; } ; block_or_error: '{' inner_statement_list '}' { $$ = $2; } | error { $$ = []; } ; identifier_maybe_readonly: identifier_not_reserved { $$ = $1; } | T_READONLY { $$ = Node\Identifier[$1]; } ; function_declaration_statement: T_FUNCTION optional_ref identifier_maybe_readonly '(' parameter_list ')' optional_return_type block_or_error { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } | attributes T_FUNCTION optional_ref identifier_maybe_readonly '(' parameter_list ')' optional_return_type block_or_error { $$ = Stmt\Function_[$4, ['byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } ; class_declaration_statement: class_entry_type identifier_not_reserved extends_from implements_list '{' class_statement_list '}' { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6, 'attrGroups' => []]]; $this->checkClass($$, #2); } | attributes class_entry_type identifier_not_reserved extends_from implements_list '{' class_statement_list '}' { $$ = Stmt\Class_[$3, ['type' => $2, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]]; $this->checkClass($$, #3); } | optional_attributes T_INTERFACE identifier_not_reserved interface_extends_list '{' class_statement_list '}' { $$ = Stmt\Interface_[$3, ['extends' => $4, 'stmts' => $6, 'attrGroups' => $1]]; $this->checkInterface($$, #3); } | optional_attributes T_TRAIT identifier_not_reserved '{' class_statement_list '}' { $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; } | optional_attributes T_ENUM identifier_not_reserved enum_scalar_type implements_list '{' class_statement_list '}' { $$ = Stmt\Enum_[$3, ['scalarType' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]]; $this->checkEnum($$, #3); } ; enum_scalar_type: /* empty */ { $$ = null; } | ':' type { $$ = $2; } enum_case_expr: /* empty */ { $$ = null; } | '=' expr { $$ = $2; } ; class_entry_type: T_CLASS { $$ = 0; } | class_modifiers T_CLASS { $$ = $1; } ; class_modifiers: class_modifier { $$ = $1; } | class_modifiers class_modifier { $this->checkClassModifier($1, $2, #2); $$ = $1 | $2; } ; class_modifier: T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } ; extends_from: /* empty */ { $$ = null; } | T_EXTENDS class_name { $$ = $2; } ; interface_extends_list: /* empty */ { $$ = array(); } | T_EXTENDS class_name_list { $$ = $2; } ; implements_list: /* empty */ { $$ = array(); } | T_IMPLEMENTS class_name_list { $$ = $2; } ; class_name_list: non_empty_class_name_list no_comma { $$ = $1; } ; non_empty_class_name_list: class_name { init($1); } | non_empty_class_name_list ',' class_name { push($1, $3); } ; for_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } ; foreach_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } ; declare_statement: non_empty_statement { $$ = toArray($1); } | ';' { $$ = null; } | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } ; declare_list: non_empty_declare_list no_comma { $$ = $1; } ; non_empty_declare_list: declare_list_element { init($1); } | non_empty_declare_list ',' declare_list_element { push($1, $3); } ; declare_list_element: identifier_not_reserved '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; } ; switch_case_list: '{' case_list '}' { $$ = $2; } | '{' ';' case_list '}' { $$ = $3; } | ':' case_list T_ENDSWITCH ';' { $$ = $2; } | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } ; case_list: /* empty */ { init(); } | case_list case { push($1, $2); } ; case: T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } ; case_separator: ':' | ';' ; match: T_MATCH '(' expr ')' '{' match_arm_list '}' { $$ = Expr\Match_[$3, $6]; } ; match_arm_list: /* empty */ { $$ = []; } | non_empty_match_arm_list optional_comma { $$ = $1; } ; non_empty_match_arm_list: match_arm { init($1); } | non_empty_match_arm_list ',' match_arm { push($1, $3); } ; match_arm: expr_list_allow_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[$1, $3]; } | T_DEFAULT optional_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[null, $4]; } ; while_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } ; elseif_list: /* empty */ { init(); } | elseif_list elseif { push($1, $2); } ; elseif: T_ELSEIF '(' expr ')' statement { $$ = Stmt\ElseIf_[$3, toArray($5)]; } ; new_elseif_list: /* empty */ { init(); } | new_elseif_list new_elseif { push($1, $2); } ; new_elseif: T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = Stmt\ElseIf_[$3, $6]; $this->fixupAlternativeElse($$); } ; else_single: /* empty */ { $$ = null; } | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } ; new_else_single: /* empty */ { $$ = null; } | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; $this->fixupAlternativeElse($$); } ; foreach_variable: variable { $$ = array($1, false); } | ampersand variable { $$ = array($2, true); } | list_expr { $$ = array($1, false); } | array_short_syntax { $$ = array($1, false); } ; parameter_list: non_empty_parameter_list optional_comma { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_parameter_list: parameter { init($1); } | non_empty_parameter_list ',' parameter { push($1, $3); } ; optional_property_modifiers: /* empty */ { $$ = 0; } | optional_property_modifiers property_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } ; property_modifier: T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } ; parameter: optional_attributes optional_property_modifiers optional_type_without_static optional_arg_ref optional_ellipsis plain_variable { $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1); $this->checkParam($$); } | optional_attributes optional_property_modifiers optional_type_without_static optional_arg_ref optional_ellipsis plain_variable '=' expr { $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1); $this->checkParam($$); } | optional_attributes optional_property_modifiers optional_type_without_static optional_arg_ref optional_ellipsis error { $$ = new Node\Param(Expr\Error[], null, $3, $4, $5, attributes(), $2, $1); } ; type_expr: type { $$ = $1; } | '?' type { $$ = Node\NullableType[$2]; } | union_type { $$ = Node\UnionType[$1]; } | intersection_type { $$ = $1; } ; type: type_without_static { $$ = $1; } | T_STATIC { $$ = Node\Name['static']; } ; type_without_static: name { $$ = $this->handleBuiltinTypes($1); } | T_ARRAY { $$ = Node\Identifier['array']; } | T_CALLABLE { $$ = Node\Identifier['callable']; } ; union_type_element: type { $$ = $1; } | '(' intersection_type ')' { $$ = $2; } ; union_type: union_type_element '|' union_type_element { init($1, $3); } | union_type '|' union_type_element { push($1, $3); } ; union_type_without_static_element: type_without_static { $$ = $1; } | '(' intersection_type_without_static ')' { $$ = $2; } ; union_type_without_static: union_type_without_static_element '|' union_type_without_static_element { init($1, $3); } | union_type_without_static '|' union_type_without_static_element { push($1, $3); } ; intersection_type_list: type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { init($1, $3); } | intersection_type_list T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { push($1, $3); } ; intersection_type: intersection_type_list { $$ = Node\IntersectionType[$1]; } ; intersection_type_without_static_list: type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static { init($1, $3); } | intersection_type_without_static_list T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static { push($1, $3); } ; intersection_type_without_static: intersection_type_without_static_list { $$ = Node\IntersectionType[$1]; } ; type_expr_without_static: type_without_static { $$ = $1; } | '?' type_without_static { $$ = Node\NullableType[$2]; } | union_type_without_static { $$ = Node\UnionType[$1]; } | intersection_type_without_static { $$ = $1; } ; optional_type_without_static: /* empty */ { $$ = null; } | type_expr_without_static { $$ = $1; } ; optional_return_type: /* empty */ { $$ = null; } | ':' type_expr { $$ = $2; } | ':' error { $$ = null; } ; argument_list: '(' ')' { $$ = array(); } | '(' non_empty_argument_list optional_comma ')' { $$ = $2; } | '(' variadic_placeholder ')' { init($2); } ; variadic_placeholder: T_ELLIPSIS { $$ = Node\VariadicPlaceholder[]; } ; non_empty_argument_list: argument { init($1); } | non_empty_argument_list ',' argument { push($1, $3); } ; argument: expr { $$ = Node\Arg[$1, false, false]; } | ampersand variable { $$ = Node\Arg[$2, true, false]; } | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } | identifier_maybe_reserved ':' expr { $$ = new Node\Arg($3, false, false, attributes(), $1); } ; global_var_list: non_empty_global_var_list no_comma { $$ = $1; } ; non_empty_global_var_list: non_empty_global_var_list ',' global_var { push($1, $3); } | global_var { init($1); } ; global_var: simple_variable { $$ = $1; } ; static_var_list: non_empty_static_var_list no_comma { $$ = $1; } ; non_empty_static_var_list: non_empty_static_var_list ',' static_var { push($1, $3); } | static_var { init($1); } ; static_var: plain_variable { $$ = Stmt\StaticVar[$1, null]; } | plain_variable '=' expr { $$ = Stmt\StaticVar[$1, $3]; } ; class_statement_list_ex: class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } | /* empty */ { init(); } ; class_statement_list: class_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; class_statement: optional_attributes variable_modifiers optional_type_without_static property_declaration_list semi { $$ = new Stmt\Property($2, $4, attributes(), $3, $1); $this->checkProperty($$, #2); } | optional_attributes method_modifiers T_CONST class_const_list semi { $$ = new Stmt\ClassConst($4, $2, attributes(), $1); $this->checkClassConst($$, #2); } | optional_attributes method_modifiers T_FUNCTION optional_ref identifier_maybe_reserved '(' parameter_list ')' optional_return_type method_body { $$ = Stmt\ClassMethod[$5, ['type' => $2, 'byRef' => $4, 'params' => $7, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; $this->checkClassMethod($$, #2); } | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } | optional_attributes T_CASE identifier_maybe_reserved enum_case_expr semi { $$ = Stmt\EnumCase[$3, $4, $1]; } | error { $$ = null; /* will be skipped */ } ; trait_adaptations: ';' { $$ = array(); } | '{' trait_adaptation_list '}' { $$ = $2; } ; trait_adaptation_list: /* empty */ { init(); } | trait_adaptation_list trait_adaptation { push($1, $2); } ; trait_adaptation: trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } | trait_method_reference T_AS member_modifier identifier_maybe_reserved ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } | trait_method_reference T_AS member_modifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } | trait_method_reference T_AS identifier_not_reserved ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } | trait_method_reference T_AS reserved_non_modifiers_identifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } ; trait_method_reference_fully_qualified: name T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved { $$ = array($1, $3); } ; trait_method_reference: trait_method_reference_fully_qualified { $$ = $1; } | identifier_maybe_reserved { $$ = array(null, $1); } ; method_body: ';' /* abstract method */ { $$ = null; } | block_or_error { $$ = $1; } ; variable_modifiers: non_empty_member_modifiers { $$ = $1; } | T_VAR { $$ = 0; } ; method_modifiers: /* empty */ { $$ = 0; } | non_empty_member_modifiers { $$ = $1; } ; non_empty_member_modifiers: member_modifier { $$ = $1; } | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } ; member_modifier: T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } ; property_declaration_list: non_empty_property_declaration_list no_comma { $$ = $1; } ; non_empty_property_declaration_list: property_declaration { init($1); } | non_empty_property_declaration_list ',' property_declaration { push($1, $3); } ; property_decl_name: T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } ; property_declaration: property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } | property_decl_name '=' expr { $$ = Stmt\PropertyProperty[$1, $3]; } ; expr_list_forbid_comma: non_empty_expr_list no_comma { $$ = $1; } ; expr_list_allow_comma: non_empty_expr_list optional_comma { $$ = $1; } ; non_empty_expr_list: non_empty_expr_list ',' expr { push($1, $3); } | expr { init($1); } ; for_expr: /* empty */ { $$ = array(); } | expr_list_forbid_comma { $$ = $1; } ; expr: variable { $$ = $1; } | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } | array_short_syntax '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; } | new_expr { $$ = $1; } | match { $$ = $1; } | T_CLONE expr { $$ = Expr\Clone_[$2]; } | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } | variable T_INC { $$ = Expr\PostInc[$1]; } | T_INC variable { $$ = Expr\PreInc [$2]; } | variable T_DEC { $$ = Expr\PostDec[$1]; } | T_DEC variable { $$ = Expr\PreDec [$2]; } | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' expr { $$ = Expr\BooleanNot[$2]; } | '~' expr { $$ = Expr\BitwiseNot[$2]; } | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } | '(' expr ')' { $$ = $2; } | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } | T_ISSET '(' expr_list_allow_comma ')' { $$ = Expr\Isset_[$3]; } | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } | T_EVAL '(' expr ')' { $$ = Expr\Eval_[$3]; } | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } | T_DOUBLE_CAST expr { $attrs = attributes(); $attrs['kind'] = $this->getFloatCastKind($1); $$ = new Expr\Cast\Double($2, $attrs); } | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } | T_EXIT exit_expr { $attrs = attributes(); $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; $$ = new Expr\Exit_($2, $attrs); } | '@' expr { $$ = Expr\ErrorSuppress[$2]; } | scalar { $$ = $1; } | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } | T_PRINT expr { $$ = Expr\Print_[$2]; } | T_YIELD { $$ = Expr\Yield_[null, null]; } | T_YIELD expr { $$ = Expr\Yield_[$2, null]; } | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } | T_THROW expr { $$ = Expr\Throw_[$2]; } | T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8, 'attrGroups' => []]]; } | T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => []]]; } | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => []]]; } | attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => $1]]; } | attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $4, 'params' => $6, 'returnType' => $8, 'expr' => $10, 'attrGroups' => $1]]; } | attributes T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => false, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } | attributes T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => true, 'byRef' => $4, 'params' => $6, 'uses' => $8, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; } ; anonymous_class: optional_attributes T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3); $this->checkClass($$[0], -1); } ; new_expr: T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } | T_NEW anonymous_class { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } ; lexical_vars: /* empty */ { $$ = array(); } | T_USE '(' lexical_var_list ')' { $$ = $3; } ; lexical_var_list: non_empty_lexical_var_list optional_comma { $$ = $1; } ; non_empty_lexical_var_list: lexical_var { init($1); } | non_empty_lexical_var_list ',' lexical_var { push($1, $3); } ; lexical_var: optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } ; name_readonly: T_READONLY { $$ = Name[$1]; } ; function_call: name argument_list { $$ = Expr\FuncCall[$1, $2]; } | name_readonly argument_list { $$ = Expr\FuncCall[$1, $2]; } | callable_expr argument_list { $$ = Expr\FuncCall[$1, $2]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list { $$ = Expr\StaticCall[$1, $3, $4]; } ; class_name: T_STATIC { $$ = Name[$1]; } | name { $$ = $1; } ; name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } ; class_name_reference: class_name { $$ = $1; } | new_variable { $$ = $1; } | '(' expr ')' { $$ = $2; } | error { $$ = Expr\Error[]; $this->errorState = 2; } ; class_name_or_var: class_name { $$ = $1; } | fully_dereferencable { $$ = $1; } ; exit_expr: /* empty */ { $$ = null; } | '(' optional_expr ')' { $$ = $2; } ; backticks_expr: /* empty */ { $$ = array(); } | T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); } | encaps_list { parseEncapsed($1, '`', true); $$ = $1; } ; ctor_arguments: /* empty */ { $$ = array(); } | argument_list { $$ = $1; } ; constant: name { $$ = Expr\ConstFetch[$1]; } | T_LINE { $$ = Scalar\MagicConst\Line[]; } | T_FILE { $$ = Scalar\MagicConst\File[]; } | T_DIR { $$ = Scalar\MagicConst\Dir[]; } | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } ; class_constant: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved { $$ = Expr\ClassConstFetch[$1, $3]; } /* We interpret an isolated FOO:: as an unfinished class constant fetch. It could also be an unfinished static property fetch or unfinished scoped call. */ | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error { $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; } ; array_short_syntax: '[' array_pair_list ']' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; $$ = new Expr\Array_($2, $attrs); } ; dereferencable_scalar: T_ARRAY '(' array_pair_list ')' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; $$ = new Expr\Array_($3, $attrs); } | array_short_syntax { $$ = $1; } | T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes()); } | '"' encaps_list '"' { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } ; scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes()); } | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } | dereferencable_scalar { $$ = $1; } | constant { $$ = $1; } | class_constant { $$ = $1; } | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } | T_START_HEREDOC T_END_HEREDOC { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), true); } | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } ; optional_expr: /* empty */ { $$ = null; } | expr { $$ = $1; } ; fully_dereferencable: variable { $$ = $1; } | '(' expr ')' { $$ = $2; } | dereferencable_scalar { $$ = $1; } | class_constant { $$ = $1; } ; array_object_dereferencable: fully_dereferencable { $$ = $1; } | constant { $$ = $1; } ; callable_expr: callable_variable { $$ = $1; } | '(' expr ')' { $$ = $2; } | dereferencable_scalar { $$ = $1; } ; callable_variable: simple_variable { $$ = $1; } | array_object_dereferencable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | array_object_dereferencable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } | function_call { $$ = $1; } | array_object_dereferencable T_OBJECT_OPERATOR property_name argument_list { $$ = Expr\MethodCall[$1, $3, $4]; } | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list { $$ = Expr\NullsafeMethodCall[$1, $3, $4]; } ; optional_plain_variable: /* empty */ { $$ = null; } | plain_variable { $$ = $1; } ; variable: callable_variable { $$ = $1; } | static_member { $$ = $1; } | array_object_dereferencable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; } ; simple_variable: plain_variable { $$ = $1; } | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } | '$' simple_variable { $$ = Expr\Variable[$2]; } | '$' error { $$ = Expr\Variable[Expr\Error[]]; $this->errorState = 2; } ; static_member_prop_name: simple_variable { $var = $1->name; $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } ; static_member: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } ; new_variable: simple_variable { $$ = $1; } | new_variable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | new_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } | new_variable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; } | class_name T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } | new_variable T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } ; member_name: identifier_maybe_reserved { $$ = $1; } | '{' expr '}' { $$ = $2; } | simple_variable { $$ = $1; } ; property_name: identifier_not_reserved { $$ = $1; } | '{' expr '}' { $$ = $2; } | simple_variable { $$ = $1; } | error { $$ = Expr\Error[]; $this->errorState = 2; } ; list_expr: T_LIST '(' inner_array_pair_list ')' { $$ = Expr\List_[$3]; } ; array_pair_list: inner_array_pair_list { $$ = $1; $end = count($$)-1; if ($$[$end] === null) array_pop($$); } ; comma_or_error: ',' | error { /* do nothing -- prevent default action of $$=$1. See #551. */ } ; inner_array_pair_list: inner_array_pair_list comma_or_error array_pair { push($1, $3); } | array_pair { init($1); } ; array_pair: expr { $$ = Expr\ArrayItem[$1, null, false]; } | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } | expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; } | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } | /* empty */ { $$ = null; } ; encaps_list: encaps_list encaps_var { push($1, $2); } | encaps_list encaps_string_part { push($1, $2); } | encaps_var { init($1); } | encaps_string_part encaps_var { init($1, $2); } ; encaps_string_part: T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } ; encaps_str_varname: T_STRING_VARNAME { $$ = Expr\Variable[$1]; } ; encaps_var: plain_variable { $$ = $1; } | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | plain_variable T_OBJECT_OPERATOR identifier_not_reserved { $$ = Expr\PropertyFetch[$1, $3]; } | plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier_not_reserved { $$ = Expr\NullsafePropertyFetch[$1, $3]; } | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' { $$ = Expr\ArrayDimFetch[$2, $4]; } | T_CURLY_OPEN variable '}' { $$ = $2; } ; encaps_var_offset: T_STRING { $$ = Scalar\String_[$1]; } | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } | '-' T_NUM_STRING { $$ = $this->parseNumString('-' . $2, attributes()); } | plain_variable { $$ = $1; } ; %% php-parser/grammar/rebuildParsers.php000064400000004265150250175720013765 0ustar00 'Php5', __DIR__ . '/php7.y' => 'Php7', ]; $tokensFile = __DIR__ . '/tokens.y'; $tokensTemplate = __DIR__ . '/tokens.template'; $skeletonFile = __DIR__ . '/parser.template'; $tmpGrammarFile = __DIR__ . '/tmp_parser.phpy'; $tmpResultFile = __DIR__ . '/tmp_parser.php'; $resultDir = __DIR__ . '/../lib/PhpParser/Parser'; $tokensResultsFile = $resultDir . '/Tokens.php'; $kmyacc = getenv('KMYACC'); if (!$kmyacc) { // Use phpyacc from dev dependencies by default. $kmyacc = __DIR__ . '/../vendor/bin/phpyacc'; } $options = array_flip($argv); $optionDebug = isset($options['--debug']); $optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']); /////////////////// /// Main script /// /////////////////// $tokens = file_get_contents($tokensFile); foreach ($grammarFileToName as $grammarFile => $name) { echo "Building temporary $name grammar file.\n"; $grammarCode = file_get_contents($grammarFile); $grammarCode = str_replace('%tokens', $tokens, $grammarCode); $grammarCode = preprocessGrammar($grammarCode); file_put_contents($tmpGrammarFile, $grammarCode); $additionalArgs = $optionDebug ? '-t -v' : ''; echo "Building $name parser.\n"; $output = execCmd("$kmyacc $additionalArgs -m $skeletonFile -p $name $tmpGrammarFile"); $resultCode = file_get_contents($tmpResultFile); $resultCode = removeTrailingWhitespace($resultCode); ensureDirExists($resultDir); file_put_contents("$resultDir/$name.php", $resultCode); unlink($tmpResultFile); echo "Building token definition.\n"; $output = execCmd("$kmyacc -m $tokensTemplate $tmpGrammarFile"); rename($tmpResultFile, $tokensResultsFile); if (!$optionKeepTmpGrammar) { unlink($tmpGrammarFile); } } //////////////////////////////// /// Utility helper functions /// //////////////////////////////// function ensureDirExists($dir) { if (!is_dir($dir)) { mkdir($dir, 0777, true); } } function execCmd($cmd) { $output = trim(shell_exec("$cmd 2>&1")); if ($output !== "") { echo "> " . $cmd . "\n"; echo $output; } return $output; } php-parser/grammar/tokens.y000064400000005201150250175720011752 0ustar00/* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for * both. This is enforced by sharing this token file. */ %right T_THROW %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' %left T_LOGICAL_OR %left T_LOGICAL_XOR %left T_LOGICAL_AND %right T_PRINT %right T_YIELD %right T_DOUBLE_ARROW %right T_YIELD_FROM %left '=' 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 %left '?' ':' %right T_COALESCE %left T_BOOLEAN_OR %left T_BOOLEAN_AND %left '|' %left '^' %left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL %left T_SL T_SR %left '+' '-' '.' %left '*' '/' '%' %right '!' %nonassoc T_INSTANCEOF %right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' %right T_POW %right '[' %nonassoc T_NEW T_CLONE %token T_EXIT %token T_IF %left T_ELSEIF %left T_ELSE %left T_ENDIF %token T_LNUMBER %token T_DNUMBER %token T_STRING %token T_STRING_VARNAME %token T_VARIABLE %token T_NUM_STRING %token T_INLINE_HTML %token T_ENCAPSED_AND_WHITESPACE %token T_CONSTANT_ENCAPSED_STRING %token T_ECHO %token T_DO %token T_WHILE %token T_ENDWHILE %token T_FOR %token T_ENDFOR %token T_FOREACH %token T_ENDFOREACH %token T_DECLARE %token T_ENDDECLARE %token T_AS %token T_SWITCH %token T_MATCH %token T_ENDSWITCH %token T_CASE %token T_DEFAULT %token T_BREAK %token T_CONTINUE %token T_GOTO %token T_FUNCTION %token T_FN %token T_CONST %token T_RETURN %token T_TRY %token T_CATCH %token T_FINALLY %token T_THROW %token T_USE %token T_INSTEADOF %token T_GLOBAL %right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC T_READONLY %token T_VAR %token T_UNSET %token T_ISSET %token T_EMPTY %token T_HALT_COMPILER %token T_CLASS %token T_TRAIT %token T_INTERFACE %token T_ENUM %token T_EXTENDS %token T_IMPLEMENTS %token T_OBJECT_OPERATOR %token T_NULLSAFE_OBJECT_OPERATOR %token T_DOUBLE_ARROW %token T_LIST %token T_ARRAY %token T_CALLABLE %token T_CLASS_C %token T_TRAIT_C %token T_METHOD_C %token T_FUNC_C %token T_LINE %token T_FILE %token T_START_HEREDOC %token T_END_HEREDOC %token T_DOLLAR_OPEN_CURLY_BRACES %token T_CURLY_OPEN %token T_PAAMAYIM_NEKUDOTAYIM %token T_NAMESPACE %token T_NS_C %token T_DIR %token T_NS_SEPARATOR %token T_ELLIPSIS %token T_NAME_FULLY_QUALIFIED %token T_NAME_QUALIFIED %token T_NAME_RELATIVE %token T_ATTRIBUTE %token T_ENUM php-parser/bin/php-parse000064400000014146150250175720011231 0ustar00#!/usr/bin/env php [ 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments' ]]); $parser = (new PhpParser\ParserFactory)->create( PhpParser\ParserFactory::PREFER_PHP7, $lexer ); $dumper = new PhpParser\NodeDumper([ 'dumpComments' => true, 'dumpPositions' => $attributes['with-positions'], ]); $prettyPrinter = new PhpParser\PrettyPrinter\Standard; $traverser = new PhpParser\NodeTraverser(); $traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); foreach ($files as $file) { if (strpos($file, ' Code $code\n"); } else { if (!file_exists($file)) { fwrite(STDERR, "File $file does not exist.\n"); exit(1); } $code = file_get_contents($file); fwrite(STDERR, "====> File $file:\n"); } if ($attributes['with-recovery']) { $errorHandler = new PhpParser\ErrorHandler\Collecting; $stmts = $parser->parse($code, $errorHandler); foreach ($errorHandler->getErrors() as $error) { $message = formatErrorMessage($error, $code, $attributes['with-column-info']); fwrite(STDERR, $message . "\n"); } if (null === $stmts) { continue; } } else { try { $stmts = $parser->parse($code); } catch (PhpParser\Error $error) { $message = formatErrorMessage($error, $code, $attributes['with-column-info']); fwrite(STDERR, $message . "\n"); exit(1); } } foreach ($operations as $operation) { if ('dump' === $operation) { fwrite(STDERR, "==> Node dump:\n"); echo $dumper->dump($stmts, $code), "\n"; } elseif ('pretty-print' === $operation) { fwrite(STDERR, "==> Pretty print:\n"); echo $prettyPrinter->prettyPrintFile($stmts), "\n"; } elseif ('json-dump' === $operation) { fwrite(STDERR, "==> JSON dump:\n"); echo json_encode($stmts, JSON_PRETTY_PRINT), "\n"; } elseif ('var-dump' === $operation) { fwrite(STDERR, "==> var_dump():\n"); var_dump($stmts); } elseif ('resolve-names' === $operation) { fwrite(STDERR, "==> Resolved names.\n"); $stmts = $traverser->traverse($stmts); } } } function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) { if ($withColumnInfo && $e->hasColumnInfo()) { return $e->getMessageWithColumnInfo($code); } else { return $e->getMessage(); } } function showHelp($error = '') { if ($error) { fwrite(STDERR, $error . "\n\n"); } fwrite($error ? STDERR : STDOUT, << false, 'with-positions' => false, 'with-recovery' => false, ]; array_shift($args); $parseOptions = true; foreach ($args as $arg) { if (!$parseOptions) { $files[] = $arg; continue; } switch ($arg) { case '--dump': case '-d': $operations[] = 'dump'; break; case '--pretty-print': case '-p': $operations[] = 'pretty-print'; break; case '--json-dump': case '-j': $operations[] = 'json-dump'; break; case '--var-dump': $operations[] = 'var-dump'; break; case '--resolve-names': case '-N'; $operations[] = 'resolve-names'; break; case '--with-column-info': case '-c'; $attributes['with-column-info'] = true; break; case '--with-positions': case '-P': $attributes['with-positions'] = true; break; case '--with-recovery': case '-r': $attributes['with-recovery'] = true; break; case '--help': case '-h'; showHelp(); break; case '--': $parseOptions = false; break; default: if ($arg[0] === '-') { showHelp("Invalid operation $arg."); } else { $files[] = $arg; } } } return [$operations, $files, $attributes]; } php-parser/composer.json000064400000001460150250175720011354 0ustar00{ "name": "nikic/php-parser", "type": "library", "description": "A PHP parser written in PHP", "keywords": [ "php", "parser" ], "license": "BSD-3-Clause", "authors": [ { "name": "Nikita Popov" } ], "require": { "php": ">=7.0", "ext-tokenizer": "*" }, "require-dev": { "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0", "ircmaxell/php-yacc": "^0.0.7" }, "extra": { "branch-alias": { "dev-master": "4.9-dev" } }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" } }, "autoload-dev": { "psr-4": { "PhpParser\\": "test/PhpParser/" } }, "bin": [ "bin/php-parse" ] } php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php000064400000004067150250175720020601 0ustar00attrGroups = $attrGroups; $this->args = $args; $this->extends = $extends; $this->implements = $implements; $this->stmts = $stmts; } public static function fromNewNode(Expr\New_ $newNode) { $class = $newNode->class; assert($class instanceof Node\Stmt\Class_); // We don't assert that $class->name is null here, to allow consumers to assign unique names // to anonymous classes for their own purposes. We simplify ignore the name here. return new self( $class->attrGroups, $newNode->args, $class->extends, $class->implements, $class->stmts, $newNode->getAttributes() ); } public function getType() : string { return 'Expr_PrintableNewAnonClass'; } public function getSubNodeNames() : array { return ['attrGroups', 'args', 'extends', 'implements', 'stmts']; } } php-parser/lib/PhpParser/Internal/DiffElem.php000064400000001054150250175720015243 0ustar00type = $type; $this->old = $old; $this->new = $new; } } php-parser/lib/PhpParser/Internal/Differ.php000064400000011072150250175720014770 0ustar00isEqual = $isEqual; } /** * Calculate diff (edit script) from $old to $new. * * @param array $old Original array * @param array $new New array * * @return DiffElem[] Diff (edit script) */ public function diff(array $old, array $new) { list($trace, $x, $y) = $this->calculateTrace($old, $new); return $this->extractDiff($trace, $x, $y, $old, $new); } /** * Calculate diff, including "replace" operations. * * If a sequence of remove operations is followed by the same number of add operations, these * will be coalesced into replace operations. * * @param array $old Original array * @param array $new New array * * @return DiffElem[] Diff (edit script), including replace operations */ public function diffWithReplacements(array $old, array $new) { return $this->coalesceReplacements($this->diff($old, $new)); } private function calculateTrace(array $a, array $b) { $n = \count($a); $m = \count($b); $max = $n + $m; $v = [1 => 0]; $trace = []; for ($d = 0; $d <= $max; $d++) { $trace[] = $v; for ($k = -$d; $k <= $d; $k += 2) { if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { $x = $v[$k+1]; } else { $x = $v[$k-1] + 1; } $y = $x - $k; while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) { $x++; $y++; } $v[$k] = $x; if ($x >= $n && $y >= $m) { return [$trace, $x, $y]; } } } throw new \Exception('Should not happen'); } private function extractDiff(array $trace, int $x, int $y, array $a, array $b) { $result = []; for ($d = \count($trace) - 1; $d >= 0; $d--) { $v = $trace[$d]; $k = $x - $y; if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { $prevK = $k + 1; } else { $prevK = $k - 1; } $prevX = $v[$prevK]; $prevY = $prevX - $prevK; while ($x > $prevX && $y > $prevY) { $result[] = new DiffElem(DiffElem::TYPE_KEEP, $a[$x-1], $b[$y-1]); $x--; $y--; } if ($d === 0) { break; } while ($x > $prevX) { $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $a[$x-1], null); $x--; } while ($y > $prevY) { $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $b[$y-1]); $y--; } } return array_reverse($result); } /** * Coalesce equal-length sequences of remove+add into a replace operation. * * @param DiffElem[] $diff * @return DiffElem[] */ private function coalesceReplacements(array $diff) { $newDiff = []; $c = \count($diff); for ($i = 0; $i < $c; $i++) { $diffType = $diff[$i]->type; if ($diffType !== DiffElem::TYPE_REMOVE) { $newDiff[] = $diff[$i]; continue; } $j = $i; while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) { $j++; } $k = $j; while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) { $k++; } if ($j - $i === $k - $j) { $len = $j - $i; for ($n = 0; $n < $len; $n++) { $newDiff[] = new DiffElem( DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new ); } } else { for (; $i < $k; $i++) { $newDiff[] = $diff[$i]; } } $i = $k - 1; } return $newDiff; } } php-parser/lib/PhpParser/Internal/TokenStream.php000064400000022053150250175720016026 0ustar00tokens = $tokens; $this->indentMap = $this->calcIndentMap(); } /** * Whether the given position is immediately surrounded by parenthesis. * * @param int $startPos Start position * @param int $endPos End position * * @return bool */ public function haveParens(int $startPos, int $endPos) : bool { return $this->haveTokenImmediatelyBefore($startPos, '(') && $this->haveTokenImmediatelyAfter($endPos, ')'); } /** * Whether the given position is immediately surrounded by braces. * * @param int $startPos Start position * @param int $endPos End position * * @return bool */ public function haveBraces(int $startPos, int $endPos) : bool { return ($this->haveTokenImmediatelyBefore($startPos, '{') || $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN)) && $this->haveTokenImmediatelyAfter($endPos, '}'); } /** * Check whether the position is directly preceded by a certain token type. * * During this check whitespace and comments are skipped. * * @param int $pos Position before which the token should occur * @param int|string $expectedTokenType Token to check for * * @return bool Whether the expected token was found */ public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool { $tokens = $this->tokens; $pos--; for (; $pos >= 0; $pos--) { $tokenType = $tokens[$pos][0]; if ($tokenType === $expectedTokenType) { return true; } if ($tokenType !== \T_WHITESPACE && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { break; } } return false; } /** * Check whether the position is directly followed by a certain token type. * * During this check whitespace and comments are skipped. * * @param int $pos Position after which the token should occur * @param int|string $expectedTokenType Token to check for * * @return bool Whether the expected token was found */ public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool { $tokens = $this->tokens; $pos++; for (; $pos < \count($tokens); $pos++) { $tokenType = $tokens[$pos][0]; if ($tokenType === $expectedTokenType) { return true; } if ($tokenType !== \T_WHITESPACE && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { break; } } return false; } public function skipLeft(int $pos, $skipTokenType) { $tokens = $this->tokens; $pos = $this->skipLeftWhitespace($pos); if ($skipTokenType === \T_WHITESPACE) { return $pos; } if ($tokens[$pos][0] !== $skipTokenType) { // Shouldn't happen. The skip token MUST be there throw new \Exception('Encountered unexpected token'); } $pos--; return $this->skipLeftWhitespace($pos); } public function skipRight(int $pos, $skipTokenType) { $tokens = $this->tokens; $pos = $this->skipRightWhitespace($pos); if ($skipTokenType === \T_WHITESPACE) { return $pos; } if ($tokens[$pos][0] !== $skipTokenType) { // Shouldn't happen. The skip token MUST be there throw new \Exception('Encountered unexpected token'); } $pos++; return $this->skipRightWhitespace($pos); } /** * Return first non-whitespace token position smaller or equal to passed position. * * @param int $pos Token position * @return int Non-whitespace token position */ public function skipLeftWhitespace(int $pos) { $tokens = $this->tokens; for (; $pos >= 0; $pos--) { $type = $tokens[$pos][0]; if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { break; } } return $pos; } /** * Return first non-whitespace position greater or equal to passed position. * * @param int $pos Token position * @return int Non-whitespace token position */ public function skipRightWhitespace(int $pos) { $tokens = $this->tokens; for ($count = \count($tokens); $pos < $count; $pos++) { $type = $tokens[$pos][0]; if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { break; } } return $pos; } public function findRight(int $pos, $findTokenType) { $tokens = $this->tokens; for ($count = \count($tokens); $pos < $count; $pos++) { $type = $tokens[$pos][0]; if ($type === $findTokenType) { return $pos; } } return -1; } /** * Whether the given position range contains a certain token type. * * @param int $startPos Starting position (inclusive) * @param int $endPos Ending position (exclusive) * @param int|string $tokenType Token type to look for * @return bool Whether the token occurs in the given range */ public function haveTokenInRange(int $startPos, int $endPos, $tokenType) { $tokens = $this->tokens; for ($pos = $startPos; $pos < $endPos; $pos++) { if ($tokens[$pos][0] === $tokenType) { return true; } } return false; } public function haveBracesInRange(int $startPos, int $endPos) { return $this->haveTokenInRange($startPos, $endPos, '{') || $this->haveTokenInRange($startPos, $endPos, T_CURLY_OPEN) || $this->haveTokenInRange($startPos, $endPos, '}'); } public function haveTagInRange(int $startPos, int $endPos): bool { return $this->haveTokenInRange($startPos, $endPos, \T_OPEN_TAG) || $this->haveTokenInRange($startPos, $endPos, \T_CLOSE_TAG); } /** * Get indentation before token position. * * @param int $pos Token position * * @return int Indentation depth (in spaces) */ public function getIndentationBefore(int $pos) : int { return $this->indentMap[$pos]; } /** * Get the code corresponding to a token offset range, optionally adjusted for indentation. * * @param int $from Token start position (inclusive) * @param int $to Token end position (exclusive) * @param int $indent By how much the code should be indented (can be negative as well) * * @return string Code corresponding to token range, adjusted for indentation */ public function getTokenCode(int $from, int $to, int $indent) : string { $tokens = $this->tokens; $result = ''; for ($pos = $from; $pos < $to; $pos++) { $token = $tokens[$pos]; if (\is_array($token)) { $type = $token[0]; $content = $token[1]; if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) { $result .= $content; } else { // TODO Handle non-space indentation if ($indent < 0) { $result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $content); } elseif ($indent > 0) { $result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $content); } else { $result .= $content; } } } else { $result .= $token; } } return $result; } /** * Precalculate the indentation at every token position. * * @return int[] Token position to indentation map */ private function calcIndentMap() { $indentMap = []; $indent = 0; foreach ($this->tokens as $token) { $indentMap[] = $indent; if ($token[0] === \T_WHITESPACE) { $content = $token[1]; $newlinePos = \strrpos($content, "\n"); if (false !== $newlinePos) { $indent = \strlen($content) - $newlinePos - 1; } } } // Add a sentinel for one past end of the file $indentMap[] = $indent; return $indentMap; } } php-parser/lib/PhpParser/NodeVisitorAbstract.php000064400000000666150250175720015755 0ustar00getNode(); } if ($node instanceof Node) { return $node; } throw new \LogicException('Expected node or builder object'); } /** * Normalizes a node to a statement. * * Expressions are wrapped in a Stmt\Expression node. * * @param Node|Builder $node The node to normalize * * @return Stmt The normalized statement node */ public static function normalizeStmt($node) : Stmt { $node = self::normalizeNode($node); if ($node instanceof Stmt) { return $node; } if ($node instanceof Expr) { return new Stmt\Expression($node); } throw new \LogicException('Expected statement or expression node'); } /** * Normalizes strings to Identifier. * * @param string|Identifier $name The identifier to normalize * * @return Identifier The normalized identifier */ public static function normalizeIdentifier($name) : Identifier { if ($name instanceof Identifier) { return $name; } if (\is_string($name)) { return new Identifier($name); } throw new \LogicException('Expected string or instance of Node\Identifier'); } /** * Normalizes strings to Identifier, also allowing expressions. * * @param string|Identifier|Expr $name The identifier to normalize * * @return Identifier|Expr The normalized identifier or expression */ public static function normalizeIdentifierOrExpr($name) { if ($name instanceof Identifier || $name instanceof Expr) { return $name; } if (\is_string($name)) { return new Identifier($name); } throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr'); } /** * Normalizes a name: Converts string names to Name nodes. * * @param Name|string $name The name to normalize * * @return Name The normalized name */ public static function normalizeName($name) : Name { if ($name instanceof Name) { return $name; } if (is_string($name)) { if (!$name) { throw new \LogicException('Name cannot be empty'); } if ($name[0] === '\\') { return new Name\FullyQualified(substr($name, 1)); } if (0 === strpos($name, 'namespace\\')) { return new Name\Relative(substr($name, strlen('namespace\\'))); } return new Name($name); } throw new \LogicException('Name must be a string or an instance of Node\Name'); } /** * Normalizes a name: Converts string names to Name nodes, while also allowing expressions. * * @param Expr|Name|string $name The name to normalize * * @return Name|Expr The normalized name or expression */ public static function normalizeNameOrExpr($name) { if ($name instanceof Expr) { return $name; } if (!is_string($name) && !($name instanceof Name)) { throw new \LogicException( 'Name must be a string or an instance of Node\Name or Node\Expr' ); } return self::normalizeName($name); } /** * Normalizes a type: Converts plain-text type names into proper AST representation. * * In particular, builtin types become Identifiers, custom types become Names and nullables * are wrapped in NullableType nodes. * * @param string|Name|Identifier|ComplexType $type The type to normalize * * @return Name|Identifier|ComplexType The normalized type */ public static function normalizeType($type) { if (!is_string($type)) { if ( !$type instanceof Name && !$type instanceof Identifier && !$type instanceof ComplexType ) { throw new \LogicException( 'Type must be a string, or an instance of Name, Identifier or ComplexType' ); } return $type; } $nullable = false; if (strlen($type) > 0 && $type[0] === '?') { $nullable = true; $type = substr($type, 1); } $builtinTypes = [ 'array', 'callable', 'bool', 'int', 'float', 'string', 'iterable', 'void', 'object', 'null', 'false', 'mixed', 'never', 'true', ]; $lowerType = strtolower($type); if (in_array($lowerType, $builtinTypes)) { $type = new Identifier($lowerType); } else { $type = self::normalizeName($type); } $notNullableTypes = [ 'void', 'mixed', 'never', ]; if ($nullable && in_array((string) $type, $notNullableTypes)) { throw new \LogicException(sprintf('%s type cannot be nullable', $type)); } return $nullable ? new NullableType($type) : $type; } /** * Normalizes a value: Converts nulls, booleans, integers, * floats, strings and arrays into their respective nodes * * @param Node\Expr|bool|null|int|float|string|array $value The value to normalize * * @return Expr The normalized value */ public static function normalizeValue($value) : Expr { if ($value instanceof Node\Expr) { return $value; } if (is_null($value)) { return new Expr\ConstFetch( new Name('null') ); } if (is_bool($value)) { return new Expr\ConstFetch( new Name($value ? 'true' : 'false') ); } if (is_int($value)) { return new Scalar\LNumber($value); } if (is_float($value)) { return new Scalar\DNumber($value); } if (is_string($value)) { return new Scalar\String_($value); } if (is_array($value)) { $items = []; $lastKey = -1; foreach ($value as $itemKey => $itemValue) { // for consecutive, numeric keys don't generate keys if (null !== $lastKey && ++$lastKey === $itemKey) { $items[] = new Expr\ArrayItem( self::normalizeValue($itemValue) ); } else { $lastKey = null; $items[] = new Expr\ArrayItem( self::normalizeValue($itemValue), self::normalizeValue($itemKey) ); } } return new Expr\Array_($items); } throw new \LogicException('Invalid value'); } /** * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. * * @param Comment\Doc|string $docComment The doc comment to normalize * * @return Comment\Doc The normalized doc comment */ public static function normalizeDocComment($docComment) : Comment\Doc { if ($docComment instanceof Comment\Doc) { return $docComment; } if (is_string($docComment)) { return new Comment\Doc($docComment); } throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); } /** * Normalizes a attribute: Converts attribute to the Attribute Group if needed. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return Node\AttributeGroup The Attribute Group */ public static function normalizeAttribute($attribute) : Node\AttributeGroup { if ($attribute instanceof Node\AttributeGroup) { return $attribute; } if (!($attribute instanceof Node\Attribute)) { throw new \LogicException('Attribute must be an instance of PhpParser\Node\Attribute or PhpParser\Node\AttributeGroup'); } return new Node\AttributeGroup([$attribute]); } /** * Adds a modifier and returns new modifier bitmask. * * @param int $modifiers Existing modifiers * @param int $modifier Modifier to set * * @return int New modifiers */ public static function addModifier(int $modifiers, int $modifier) : int { Stmt\Class_::verifyModifier($modifiers, $modifier); return $modifiers | $modifier; } /** * Adds a modifier and returns new modifier bitmask. * @return int New modifiers */ public static function addClassModifier(int $existingModifiers, int $modifierToSet) : int { Stmt\Class_::verifyClassModifier($existingModifiers, $modifierToSet); return $existingModifiers | $modifierToSet; } } php-parser/lib/PhpParser/ConstExprEvaluationException.php000064400000000126150250175720017647 0ustar00'", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_READONLY", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "';'", "'{'", "'}'", "'('", "')'", "'$'", "'`'", "']'", "'\"'", "T_ENUM", "T_NULLSAFE_OBJECT_OPERATOR", "T_ATTRIBUTE" ); protected $tokenToSymbol = array( 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 56, 164, 168, 161, 55, 168, 168, 159, 160, 53, 50, 8, 51, 52, 54, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 31, 156, 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 70, 168, 163, 36, 168, 162, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 157, 35, 158, 58, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 165, 131, 132, 133, 166, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 167 ); protected $action = array( 700, 670, 671, 672, 673, 674, 286, 675, 676, 677, 713, 714, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 0, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,-32766,-32766,-32766,-32766,-32766, -32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, 245, 246, 242, 243, 244,-32766,-32766, 678,-32766,-32766,-32766,-32766, -32766,-32766,-32766,-32766,-32766, 1229, 245, 246, 1230, 679, 680, 681, 682, 683, 684, 685, 899, 900, 747,-32766, -32766,-32766,-32766,-32766,-32766, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 716, 739, 717, 718, 719, 720, 708, 709, 710, 738, 711, 712, 697, 698, 699, 701, 702, 703, 741, 742, 743, 744, 745, 746, 875, 704, 705, 706, 707, 737, 728, 726, 727, 723, 724, 1046, 715, 721, 722, 729, 730, 732, 731, 733, 734, 55, 56, 425, 57, 58, 725, 736, 735, 755, 59, 60, -226, 61,-32766,-32766,-32766,-32766,-32766,-32766, -32766,-32766,-32766,-32766, 337,-32767,-32767,-32767,-32767, 29, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 620,-32766,-32766,-32766,-32766, 62, 63, 1046,-32766,-32766,-32766, 64, 419, 65, 294, 295, 66, 67, 68, 69, 70, 71, 72, 73, 823, 25, 302, 74, 418, 984, 986, 669, 668, 1100, 1101, 1078, 755, 755, 767, 1220, 768, 470,-32766,-32766,-32766, 341, 749, 824, 54,-32767,-32767,-32767,-32767, 98, 99, 100, 101, 102, 220, 221, 222, 362, 876,-32766, 27,-32766,-32766, -32766,-32766,-32766, 1046, 493, 126, 1080, 1079, 1081, 370, 1068, 930, 207, 478, 479, 952, 953, 954, 951, 950, 949, 128, 480, 481, 803, 1106, 1107, 1108, 1109, 1103, 1104, 319, 32, 297, 10, 211, -515, 1110, 1105, 669, 668, 1080, 1079, 1081, 220, 221, 222, 41, 364, 341, 334, 421, 336, 426, -128, -128, -128, 313, 1046, 469, -4, 824, 54, 812, 770, 207, 40, 21, 427, -128, 471, -128, 472, -128, 473, -128, 1046, 428, 220, 221, 222,-32766, 33, 34, 429, 361, 327, 52, 35, 474, -32766,-32766,-32766, 342, 357, 358, 475, 476, 48, 207, 249, 669, 668, 477, 443, 300, 795, 846, 430, 431, 28,-32766, 814,-32766,-32766,-32766,-32766,-32766,-32766,-32766, -32767,-32767,-32767,-32767,-32767, 952, 953, 954, 951, 950, 949, 422, 755, 424, 426, 826, 634, -128,-32766,-32766, 469, 824, 54, 288, 812, 1151, 755, 40, 21, 427, 317, 471, 345, 472, 129, 473, 9, 1186, 428, 769, 360, 324, 905, 33, 34, 429, 361, 1046, 415, 35, 474, 944, 1068, 315, 125, 357, 358, 475, 476,-32766, -32766,-32766, 926, 302, 477, 121, 1068, 759, 846, 430, 431, 669, 668, 423, 755, 1152, 809, 1046, 480, 766, -32766, 805,-32766,-32766,-32766,-32766, -261, 127, 347, 436, 841, 341, 1078, 1200, 426, 446, 826, 634, -4, 807, 469, 824, 54, 436, 812, 341, 755, 40, 21, 427, 444, 471, 130, 472, 1068, 473, 346, 767, 428, 768, -211, -211, -211, 33, 34, 429, 361, 308, 1076, 35, 474,-32766,-32766,-32766, 1046, 357, 358, 475, 476,-32766, -32766,-32766, 906, 120, 477, 539, 1068, 795, 846, 430, 431, 436,-32766, 341,-32766,-32766,-32766, 1046, 480, 810, -32766, 925,-32766,-32766, 754, 1080, 1079, 1081, 49,-32766, -32766,-32766, 749, 751, 426, 1201, 826, 634, -211, 30, 469, 669, 668, 436, 812, 341, 75, 40, 21, 427, -32766, 471, 1064, 472, 124, 473, 669, 668, 428, 212, -210, -210, -210, 33, 34, 429, 361, 51, 1186, 35, 474, 755,-32766,-32766,-32766, 357, 358, 475, 476, 213, 824, 54, 221, 222, 477, 20, 581, 795, 846, 430, 431, 220, 221, 222, 755, 222, 247, 78, 79, 80, 81, 341, 207, 517, 103, 104, 105, 752, 307, 131, 637, 1068, 207, 341, 207, 122, 826, 634, -210, 36, 106, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 1112, 307, 346, 436, 214, 341, 824, 54, 426, 123, 250, 129, 134, 106, 469, -32766, 572, 1112, 812, 245, 246, 40, 21, 427, 251, 471, 252, 472, 341, 473, 453, 22, 428, 207, 899, 900, 638, 33, 34, 429, 824, 54, -86, 35, 474, 220, 221, 222, 314, 357, 358, 100, 101, 102, 239, 240, 241, 645, 477, -230, 458, 589, 135, 374, 596, 597, 207, 760, 640, 648, 642, 941, 654, 929, 662, 822, 133, 307, 837, 426,-32766, 106, 749, 43, 44, 469, 45, 442, 46, 812, 826, 634, 40, 21, 427, 47, 471, 50, 472, 53, 473, 132, 608, 428, 302, 604, -280,-32766, 33, 34, 429, 824, 54, 426, 35, 474, 755, 957, -84, 469, 357, 358, 521, 812, 628, 363, 40, 21, 427, 477, 471, 575, 472, -515, 473, 847, 616, 428, -423,-32766, 11, 646, 33, 34, 429, 824, 54, 445, 35, 474, 462, 285, 578, 1111, 357, 358, 593, 369, 848, 594, 290, 826, 634, 477, 0, 0, 532, 0, 0, 325, 0, 0, 0, 0, 0, 651, 0, 0, 0, 322, 326, 0, 0, 0, 426, 0, 0, 0, 0, 323, 469, 316, 318, -516, 812, 862, 634, 40, 21, 427, 0, 471, 0, 472, 0, 473, 1158, 0, 428, 0, -414, 6, 7, 33, 34, 429, 824, 54, 426, 35, 474, 12, 14, 373, 469, 357, 358, -424, 812, 563, 754, 40, 21, 427, 477, 471, 248, 472, 839, 473, 38, 39, 428, 657, 658, 765, 813, 33, 34, 429, 821, 800, 815, 35, 474, 215, 216, 878, 869, 357, 358, 217, 870, 218, 798, 863, 826, 634, 477, 860, 858, 936, 937, 934, 820, 209, 804, 806, 808, 811, 933, 763, 764, 1100, 1101, 935, 659, 78, 335, 426, 359, 1102, 635, 639, 641, 469, 643, 644, 647, 812, 826, 634, 40, 21, 427, 649, 471, 650, 472, 652, 473, 653, 636, 428, 796, 1226, 1228, 762, 33, 34, 429, 215, 216, 845, 35, 474, 761, 217, 844, 218, 357, 358, 1227, 843, 1060, 831, 1048, 842, 1049, 477, 559, 209, 1106, 1107, 1108, 1109, 1103, 1104, 398, 1100, 1101, 829, 942, 867, 1110, 1105, 868, 1102, 457, 1225, 1194, 1192, 1177, 1157, 219, 1190, 1091, 917, 1198, 1188, 0, 826, 634, 24, -433, 26, 31, 37, 42, 76, 77, 210, 287, 292, 293, 308, 309, 310, 311, 339, 356, 416, 0, -227, -226, 16, 17, 18, 393, 454, 461, 463, 467, 553, 625, 1051, 559, 1054, 1106, 1107, 1108, 1109, 1103, 1104, 398, 907, 1116, 1050, 1026, 564, 1110, 1105, 1025, 1093, 1055, 0, 1044, 0, 1057, 1056, 219, 1059, 1058, 1075, 0, 1191, 1176, 1172, 1189, 1090, 1223, 1117, 1171, 600 ); protected $actionCheck = array( 2, 3, 4, 5, 6, 7, 14, 9, 10, 11, 12, 13, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 0, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 9, 10, 11, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 69, 70, 53, 54, 55, 9, 10, 57, 30, 116, 32, 33, 34, 35, 36, 37, 38, 80, 69, 70, 83, 71, 72, 73, 74, 75, 76, 77, 135, 136, 80, 33, 34, 35, 36, 37, 38, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 31, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 13, 134, 135, 136, 137, 138, 139, 140, 141, 142, 3, 4, 5, 6, 7, 148, 149, 150, 82, 12, 13, 160, 15, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 8, 44, 45, 46, 47, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 80, 33, 34, 35, 36, 50, 51, 13, 9, 10, 11, 56, 128, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 1, 70, 71, 72, 73, 59, 60, 37, 38, 78, 79, 80, 82, 82, 106, 85, 108, 86, 9, 10, 11, 161, 80, 1, 2, 44, 45, 46, 47, 48, 49, 50, 51, 52, 9, 10, 11, 106, 156, 30, 8, 32, 33, 34, 35, 36, 13, 116, 8, 153, 154, 155, 8, 122, 158, 30, 125, 126, 116, 117, 118, 119, 120, 121, 31, 134, 135, 156, 137, 138, 139, 140, 141, 142, 143, 145, 146, 8, 8, 133, 149, 150, 37, 38, 153, 154, 155, 9, 10, 11, 159, 8, 161, 162, 8, 164, 74, 75, 76, 77, 8, 13, 80, 0, 1, 2, 84, 158, 30, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 13, 98, 9, 10, 11, 9, 103, 104, 105, 106, 8, 70, 109, 110, 9, 10, 11, 8, 115, 116, 117, 118, 70, 30, 31, 37, 38, 124, 31, 8, 127, 128, 129, 130, 8, 30, 156, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 116, 117, 118, 119, 120, 121, 8, 82, 8, 74, 156, 157, 158, 33, 34, 80, 1, 2, 8, 84, 163, 82, 87, 88, 89, 133, 91, 70, 93, 152, 95, 108, 82, 98, 158, 8, 113, 160, 103, 104, 105, 106, 13, 108, 109, 110, 123, 122, 113, 157, 115, 116, 117, 118, 9, 10, 11, 156, 71, 124, 157, 122, 127, 128, 129, 130, 37, 38, 8, 82, 160, 156, 13, 134, 156, 30, 156, 32, 33, 34, 35, 158, 157, 148, 159, 122, 161, 80, 1, 74, 133, 156, 157, 158, 156, 80, 1, 2, 159, 84, 161, 82, 87, 88, 89, 157, 91, 157, 93, 122, 95, 161, 106, 98, 108, 100, 101, 102, 103, 104, 105, 106, 159, 116, 109, 110, 9, 10, 11, 13, 115, 116, 117, 118, 9, 10, 11, 160, 16, 124, 81, 122, 127, 128, 129, 130, 159, 30, 161, 32, 33, 34, 13, 134, 156, 30, 156, 32, 33, 153, 153, 154, 155, 70, 9, 10, 11, 80, 80, 74, 160, 156, 157, 158, 14, 80, 37, 38, 159, 84, 161, 152, 87, 88, 89, 30, 91, 160, 93, 14, 95, 37, 38, 98, 16, 100, 101, 102, 103, 104, 105, 106, 70, 82, 109, 110, 82, 33, 34, 35, 115, 116, 117, 118, 16, 1, 2, 10, 11, 124, 160, 85, 127, 128, 129, 130, 9, 10, 11, 82, 11, 14, 157, 9, 10, 11, 161, 30, 85, 53, 54, 55, 154, 57, 157, 31, 122, 30, 161, 30, 157, 156, 157, 158, 30, 69, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 144, 57, 161, 159, 16, 161, 1, 2, 74, 157, 16, 152, 157, 69, 80, 116, 161, 144, 84, 69, 70, 87, 88, 89, 16, 91, 16, 93, 161, 95, 75, 76, 98, 30, 135, 136, 31, 103, 104, 105, 1, 2, 31, 109, 110, 9, 10, 11, 31, 115, 116, 50, 51, 52, 50, 51, 52, 31, 124, 160, 75, 76, 101, 102, 111, 112, 30, 156, 157, 31, 31, 156, 157, 156, 157, 31, 31, 57, 38, 74, 33, 69, 80, 70, 70, 80, 70, 89, 70, 84, 156, 157, 87, 88, 89, 70, 91, 70, 93, 70, 95, 70, 96, 98, 71, 77, 82, 85, 103, 104, 105, 1, 2, 74, 109, 110, 82, 82, 97, 80, 115, 116, 85, 84, 92, 106, 87, 88, 89, 124, 91, 90, 93, 133, 95, 128, 94, 98, 147, 116, 97, 31, 103, 104, 105, 1, 2, 97, 109, 110, 97, 97, 100, 144, 115, 116, 100, 106, 128, 113, 161, 156, 157, 124, -1, -1, 151, -1, -1, 114, -1, -1, -1, -1, -1, 31, -1, -1, -1, 131, 131, -1, -1, -1, 74, -1, -1, -1, -1, 132, 80, 133, 133, 133, 84, 156, 157, 87, 88, 89, -1, 91, -1, 93, -1, 95, 144, -1, 98, -1, 147, 147, 147, 103, 104, 105, 1, 2, 74, 109, 110, 147, 147, 147, 80, 115, 116, 147, 84, 151, 153, 87, 88, 89, 124, 91, 31, 93, 152, 95, 156, 156, 98, 156, 156, 156, 156, 103, 104, 105, 156, 156, 156, 109, 110, 50, 51, 156, 156, 115, 116, 56, 156, 58, 156, 156, 156, 157, 124, 156, 156, 156, 156, 156, 156, 70, 156, 156, 156, 156, 156, 156, 156, 78, 79, 156, 158, 157, 157, 74, 157, 86, 157, 157, 157, 80, 157, 157, 157, 84, 156, 157, 87, 88, 89, 157, 91, 157, 93, 157, 95, 157, 157, 98, 158, 158, 158, 158, 103, 104, 105, 50, 51, 158, 109, 110, 158, 56, 158, 58, 115, 116, 158, 158, 158, 158, 158, 158, 158, 124, 135, 70, 137, 138, 139, 140, 141, 142, 143, 78, 79, 158, 158, 158, 149, 150, 158, 86, 158, 158, 158, 158, 158, 164, 159, 158, 158, 158, 158, 158, -1, 156, 157, 159, 162, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, -1, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 135, 160, 137, 138, 139, 140, 141, 142, 143, 160, 160, 160, 160, 160, 149, 150, 160, 160, 163, -1, 162, -1, 163, 163, 159, 163, 163, 163, -1, 163, 163, 163, 163, 163, 163, 163, 163, 163 ); protected $actionBase = array( 0, 229, 310, 390, 470, 103, 325, 325, 784, -2, -2, 149, -2, -2, -2, 660, 765, 799, 765, 589, 694, 870, 870, 870, 252, 404, 404, 404, 514, 177, 177, 918, 434, 118, 295, 313, 240, 491, 491, 491, 491, 138, 138, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 89, 206, 773, 550, 535, 775, 776, 777, 912, 709, 913, 856, 857, 700, 858, 859, 862, 863, 864, 855, 865, 935, 866, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 322, 592, 285, 319, 232, 44, 691, 691, 691, 691, 691, 691, 691, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 582, 530, 530, 530, 594, 860, 658, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 500, -21, -21, 492, 702, 420, 355, 216, 549, 151, 26, 26, 331, 331, 331, 331, 331, 46, 46, 5, 5, 5, 5, 153, 188, 188, 188, 188, 121, 121, 121, 121, 314, 314, 394, 394, 362, 300, 298, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 67, 656, 656, 659, 659, 522, 554, 554, 554, 554, 679, -59, -59, 381, 462, 462, 462, 528, 717, 854, 382, 382, 382, 382, 382, 382, 561, 561, 561, -3, -3, -3, 692, 115, 137, 115, 137, 678, 732, 450, 732, 338, 677, -15, 510, 810, 468, 707, 850, 711, 853, 572, 735, 267, 529, 654, 674, 463, 529, 529, 529, 529, 654, 610, 640, 608, 463, 529, 463, 718, 323, 496, 89, 570, 507, 675, 778, 293, 670, 780, 290, 373, 332, 566, 278, 435, 733, 781, 914, 917, 385, 715, 675, 675, 675, 352, 511, 278, -8, 605, 605, 605, 605, 156, 605, 605, 605, 605, 251, 276, 375, 402, 779, 657, 657, 690, 872, 869, 869, 657, 689, 657, 690, 874, 874, 874, 874, 657, 657, 657, 657, 869, 869, 869, 688, 869, 239, 703, 704, 704, 874, 742, 743, 657, 657, 712, 869, 869, 869, 712, 695, 874, 701, 741, 277, 869, 874, 672, 689, 672, 657, 701, 672, 689, 689, 672, 22, 666, 668, 873, 875, 887, 790, 662, 685, 879, 880, 876, 878, 871, 699, 744, 745, 497, 669, 671, 673, 680, 719, 682, 713, 674, 667, 667, 667, 655, 720, 655, 667, 667, 667, 667, 667, 667, 667, 667, 916, 646, 731, 714, 653, 749, 553, 573, 791, 664, 811, 900, 893, 867, 919, 881, 898, 655, 920, 739, 247, 643, 882, 783, 786, 655, 883, 655, 792, 655, 902, 812, 686, 813, 814, 667, 910, 921, 923, 924, 925, 927, 928, 929, 930, 684, 931, 750, 696, 894, 299, 877, 718, 729, 705, 788, 751, 820, 328, 932, 823, 655, 655, 794, 785, 655, 795, 756, 740, 890, 757, 895, 933, 664, 708, 896, 655, 706, 825, 934, 328, 681, 683, 888, 661, 761, 886, 911, 885, 796, 649, 663, 829, 830, 831, 693, 763, 891, 892, 889, 764, 803, 665, 805, 697, 832, 807, 884, 768, 833, 834, 899, 676, 730, 710, 698, 687, 809, 835, 897, 769, 770, 771, 848, 772, 849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 138, 138, 138, -2, -2, -2, -2, 0, 0, -2, 0, 0, 0, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 0, 0, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 599, -21, -21, -21, -21, 599, -21, -21, -21, -21, -21, -21, -21, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, -21, 599, 599, 599, -21, 382, -21, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 599, 0, 0, 599, -21, 599, -21, 599, -21, -21, 599, 599, 599, 599, 599, 599, 599, -21, -21, -21, -21, -21, -21, 0, 561, 561, 561, 561, -21, -21, -21, -21, 382, 382, 382, 382, 382, 382, 259, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 561, 561, -3, -3, 382, 382, 382, 382, 382, 259, 382, 382, 463, 689, 689, 689, 137, 137, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 463, 0, 463, 0, 382, 463, 689, 463, 657, 137, 689, 689, 463, 869, 616, 616, 616, 616, 328, 278, 0, 0, 689, 689, 0, 0, 0, 0, 0, 689, 0, 0, 0, 0, 0, 0, 869, 0, 0, 0, 0, 0, 667, 247, 0, 705, 335, 0, 0, 0, 0, 0, 0, 705, 335, 347, 347, 0, 684, 667, 667, 667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 328 ); protected $actionDefault = array( 3,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767, 544, 544, 499,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 299, 299, 299, 32767,32767,32767, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532,32767,32767,32767,32767,32767,32767, 383,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767, 389, 549,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767, 364, 365, 367, 368, 298, 552, 533, 247, 390, 548, 297, 249, 327, 503,32767,32767,32767, 329, 122, 258, 203, 502, 125, 296, 234, 382, 384, 328, 303, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 302, 458, 361, 360, 359, 460,32767, 459, 496, 496, 499,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767, 325, 487, 486, 326, 456, 330, 457, 333, 461, 464, 331, 332, 349, 350, 347, 348, 351, 462, 463, 480, 481, 478, 479, 301, 352, 353, 354, 355, 482, 483, 484, 485,32767,32767, 543, 543,32767, 32767, 282,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767, 340, 341, 471, 472,32767, 238, 238, 238, 238, 283, 238,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767, 335, 336, 334, 466, 467, 465, 432,32767,32767,32767, 434,32767, 32767,32767,32767,32767,32767,32767,32767,32767, 504,32767, 32767,32767,32767,32767, 517, 421, 171,32767, 413,32767, 171, 171, 171, 171,32767, 222, 224, 167,32767, 171, 32767, 490,32767,32767,32767,32767, 522, 345,32767,32767, 116,32767,32767,32767, 559,32767, 517,32767, 116,32767, 32767,32767,32767, 358, 337, 338, 339,32767,32767, 521, 515, 474, 475, 476, 477,32767, 468, 469, 470, 473, 32767,32767,32767,32767,32767,32767,32767,32767, 429, 435, 435,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767, 520, 519,32767, 414, 498, 188, 186, 186,32767, 208, 208,32767,32767, 190, 491, 510, 32767, 190, 173,32767, 400, 175, 498,32767,32767, 240, 32767, 240,32767, 400, 240,32767,32767, 240,32767, 415, 439,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 379, 380, 493, 506, 32767, 507,32767, 413, 343, 344, 346, 322,32767, 324, 369, 370, 371, 372, 373, 374, 375, 377,32767, 419, 32767, 422,32767,32767,32767, 257,32767, 557,32767,32767, 306, 557,32767,32767,32767, 551,32767,32767, 300,32767, 32767,32767,32767, 253,32767, 169,32767, 541,32767, 558, 32767, 515,32767, 342,32767,32767,32767,32767,32767,32767, 32767,32767,32767, 516,32767,32767,32767,32767, 229,32767, 452,32767, 116,32767,32767,32767, 189,32767,32767, 304, 248,32767,32767, 550,32767,32767,32767,32767,32767,32767, 32767,32767, 114,32767, 170,32767,32767,32767, 191,32767, 32767, 515,32767,32767,32767,32767,32767,32767,32767, 295, 32767,32767,32767,32767,32767,32767,32767, 515,32767,32767, 233,32767,32767,32767,32767,32767,32767,32767,32767,32767, 415,32767, 276,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767, 127, 127, 3, 127, 127, 260, 3, 260, 127, 260, 260, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 216, 219, 208, 208, 164, 127, 127, 268 ); protected $goto = array( 166, 140, 140, 140, 166, 187, 168, 144, 147, 141, 142, 143, 149, 163, 163, 163, 163, 144, 144, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 138, 159, 160, 161, 162, 184, 139, 185, 494, 495, 377, 496, 500, 501, 502, 503, 504, 505, 506, 507, 970, 164, 145, 146, 148, 171, 176, 186, 203, 253, 256, 258, 260, 263, 264, 265, 266, 267, 268, 269, 277, 278, 279, 280, 303, 304, 328, 329, 330, 394, 395, 396, 543, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 150, 151, 152, 167, 153, 169, 154, 204, 170, 155, 156, 157, 205, 158, 136, 621, 561, 757, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 1113, 629, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 758, 520, 531, 509, 656, 556, 1183, 750, 509, 592, 786, 1183, 888, 612, 613, 884, 617, 618, 624, 626, 631, 633, 817, 855, 855, 855, 855, 850, 856, 174, 891, 891, 1205, 1205, 177, 178, 179, 401, 402, 403, 404, 173, 202, 206, 208, 257, 259, 261, 262, 270, 271, 272, 273, 274, 275, 281, 282, 283, 284, 305, 306, 331, 332, 333, 406, 407, 408, 409, 175, 180, 254, 255, 181, 182, 183, 498, 498, 498, 498, 498, 498, 861, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 510, 586, 538, 601, 602, 510, 545, 546, 547, 548, 549, 550, 551, 552, 554, 587, 1209, 560, 350, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 400, 607, 537, 537, 569, 533, 909, 535, 535, 497, 499, 525, 541, 570, 573, 584, 591, 298, 296, 296, 296, 298, 289, 299, 611, 378, 511, 614, 595, 947, 375, 511, 437, 437, 437, 437, 437, 437, 1163, 437, 437, 437, 437, 437, 437, 437, 437, 437, 437, 1077, 948, 338, 1175, 321, 1077, 898, 898, 898, 898, 606, 898, 898, 1217, 1217, 1202, 753, 576, 605, 756, 1077, 1077, 1077, 1077, 1077, 1077, 1069, 384, 384, 384, 391, 1217, 877, 859, 857, 859, 655, 466, 512, 886, 881, 753, 384, 753, 384, 968, 384, 895, 385, 588, 353, 414, 384, 1231, 1019, 542, 1197, 1197, 1197, 568, 1094, 386, 386, 386, 904, 915, 515, 1029, 19, 15, 372, 389, 915, 940, 448, 450, 632, 340, 1216, 1216, 1114, 615, 938, 840, 555, 775, 386, 913, 1070, 1073, 1074, 399, 1069, 1182, 660, 23, 1216, 773, 1182, 544, 603, 1066, 1219, 1071, 1174, 1071, 519, 1199, 1199, 1199, 1089, 1088, 1072, 343, 523, 534, 519, 519, 772, 351, 352, 13, 579, 583, 627, 1061, 388, 782, 562, 771, 515, 783, 1181, 3, 4, 918, 956, 865, 451, 574, 1160, 464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 514, 529, 0, 0, 0, 0, 514, 0, 529, 0, 0, 0, 0, 610, 513, 516, 439, 440, 1067, 619, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 780, 1224, 0, 0, 0, 0, 0, 524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 778, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 301, 301 ); protected $gotoCheck = array( 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 57, 69, 15, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 128, 9, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 16, 102, 32, 69, 32, 32, 120, 6, 69, 32, 29, 120, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 50, 69, 69, 69, 69, 69, 69, 27, 77, 77, 77, 77, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 119, 119, 119, 119, 119, 119, 33, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 67, 110, 67, 67, 119, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 142, 57, 72, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 51, 51, 51, 51, 51, 51, 84, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 5, 5, 5, 5, 5, 5, 5, 63, 46, 124, 63, 129, 98, 63, 124, 57, 57, 57, 57, 57, 57, 133, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 98, 127, 82, 127, 57, 57, 57, 57, 57, 49, 57, 57, 144, 144, 140, 11, 40, 40, 14, 57, 57, 57, 57, 57, 57, 82, 13, 13, 13, 48, 144, 14, 14, 14, 14, 14, 57, 14, 14, 14, 11, 13, 11, 13, 102, 13, 79, 11, 70, 70, 70, 13, 13, 103, 2, 9, 9, 9, 2, 34, 125, 125, 125, 81, 13, 13, 34, 34, 34, 34, 17, 13, 8, 8, 8, 8, 18, 143, 143, 8, 8, 8, 9, 34, 25, 125, 85, 82, 82, 82, 125, 82, 121, 74, 34, 143, 24, 121, 47, 34, 116, 143, 82, 82, 82, 47, 121, 121, 121, 126, 126, 82, 58, 58, 58, 47, 47, 23, 72, 72, 58, 62, 62, 62, 114, 12, 23, 12, 23, 13, 26, 121, 30, 30, 86, 100, 71, 65, 66, 132, 109, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, 9, -1, 9, -1, -1, -1, -1, 13, 9, 9, 9, 9, 13, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, -1, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5 ); protected $gotoBase = array( 0, 0, -172, 0, 0, 353, 201, 0, 477, 149, 0, 110, 195, 117, 426, 112, 203, 140, 171, 0, 0, 0, 0, 168, 164, 157, 119, 27, 0, 205, -118, 0, -428, 266, 51, 0, 0, 0, 0, 0, 388, 0, 0, -24, 0, 0, 345, 484, 146, 133, 209, 75, 0, 0, 0, 0, 0, 107, 161, 0, 0, 0, 222, -77, 0, 106, 97, -343, 0, -94, 135, 123, -129, 0, 129, 0, 0, -50, 0, 143, 0, 159, 64, 0, 338, 132, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 121, 0, 165, 156, 0, 0, 0, 0, 0, 87, 273, 259, 0, 0, 114, 0, 150, 0, 0, -5, -91, 200, 0, 0, 84, 154, 202, 77, -48, 178, 0, 0, 93, 187, 0, 0, 0, 0, 0, 0, 136, 0, 286, 167, 102, 0, 0 ); protected $gotoDefault = array( -32768, 468, 664, 2, 665, 835, 740, 748, 598, 482, 630, 582, 380, 1193, 792, 793, 794, 381, 368, 483, 379, 410, 405, 781, 774, 776, 784, 172, 411, 787, 1, 789, 518, 825, 1020, 365, 797, 366, 590, 799, 527, 801, 802, 137, 382, 383, 528, 484, 390, 577, 816, 276, 387, 818, 367, 819, 828, 371, 465, 455, 460, 530, 557, 609, 432, 447, 571, 565, 536, 1086, 566, 864, 349, 872, 661, 880, 883, 485, 558, 894, 452, 902, 1099, 397, 908, 914, 919, 291, 922, 417, 412, 585, 927, 928, 5, 932, 622, 623, 8, 312, 955, 599, 969, 420, 1039, 1041, 486, 487, 522, 459, 508, 526, 488, 1062, 441, 413, 1065, 433, 489, 490, 434, 435, 1083, 355, 1168, 354, 449, 320, 1155, 580, 1118, 456, 1208, 1164, 348, 491, 492, 376, 1187, 392, 1203, 438, 1210, 1218, 344, 540, 567 ); protected $ruleToNonTerminal = array( 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, 12, 12, 13, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 18, 18, 19, 19, 21, 21, 17, 17, 22, 22, 23, 23, 24, 24, 25, 25, 20, 20, 26, 28, 28, 29, 30, 30, 32, 31, 31, 31, 31, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 14, 14, 54, 54, 56, 55, 55, 48, 48, 58, 58, 59, 59, 60, 60, 61, 61, 15, 16, 16, 16, 64, 64, 64, 65, 65, 68, 68, 66, 66, 70, 70, 41, 41, 50, 50, 53, 53, 53, 52, 52, 71, 42, 42, 42, 42, 72, 72, 73, 73, 74, 74, 39, 39, 35, 35, 75, 37, 37, 76, 36, 36, 38, 38, 49, 49, 49, 62, 62, 78, 78, 79, 79, 81, 81, 81, 80, 80, 63, 63, 82, 82, 82, 83, 83, 84, 84, 84, 44, 44, 85, 85, 85, 45, 45, 86, 86, 87, 87, 67, 88, 88, 88, 88, 93, 93, 94, 94, 95, 95, 95, 95, 95, 96, 97, 97, 92, 92, 89, 89, 91, 91, 99, 99, 98, 98, 98, 98, 98, 98, 90, 90, 101, 100, 100, 46, 46, 40, 40, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 34, 34, 47, 47, 106, 106, 107, 107, 107, 107, 113, 102, 102, 109, 109, 115, 115, 116, 117, 118, 118, 118, 118, 118, 118, 118, 69, 69, 57, 57, 57, 57, 103, 103, 122, 122, 119, 119, 123, 123, 123, 123, 104, 104, 104, 108, 108, 108, 114, 114, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 27, 27, 27, 27, 27, 27, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 112, 112, 105, 105, 105, 105, 129, 129, 132, 132, 131, 131, 133, 133, 51, 51, 51, 51, 135, 135, 134, 134, 134, 134, 134, 136, 136, 121, 121, 124, 124, 120, 120, 138, 137, 137, 137, 137, 125, 125, 125, 125, 111, 111, 126, 126, 126, 126, 77, 139, 139, 140, 140, 140, 110, 110, 141, 141, 142, 142, 142, 142, 142, 127, 127, 127, 127, 144, 145, 143, 143, 143, 143, 143, 143, 143, 146, 146, 146 ); protected $ruleToLength = array( 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, 2, 3, 1, 1, 7, 6, 3, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 2, 3, 1, 3, 3, 1, 3, 2, 0, 1, 1, 1, 1, 1, 3, 5, 8, 3, 5, 9, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 1, 2, 2, 5, 7, 9, 5, 6, 3, 3, 2, 2, 1, 1, 1, 0, 2, 8, 0, 4, 1, 3, 0, 1, 0, 1, 0, 1, 1, 1, 10, 7, 6, 5, 1, 2, 2, 0, 2, 0, 2, 0, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 1, 4, 0, 2, 3, 0, 2, 4, 0, 2, 0, 3, 1, 2, 1, 1, 0, 1, 3, 4, 6, 1, 1, 1, 0, 1, 0, 2, 2, 3, 3, 1, 3, 1, 2, 2, 3, 1, 1, 2, 4, 3, 1, 1, 3, 2, 0, 1, 3, 3, 9, 3, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 3, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 3, 1, 0, 1, 1, 3, 3, 4, 4, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 5, 4, 3, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 2, 1, 2, 10, 11, 3, 3, 2, 4, 4, 3, 4, 4, 4, 4, 7, 3, 2, 0, 4, 1, 3, 2, 1, 2, 2, 4, 6, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 0, 2, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 3, 1, 4, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 1, 3, 1, 1, 3, 3, 0, 2, 0, 1, 3, 1, 3, 1, 1, 1, 1, 1, 6, 4, 3, 4, 2, 4, 4, 1, 3, 1, 2, 1, 1, 4, 1, 1, 3, 6, 4, 4, 4, 4, 1, 4, 0, 1, 1, 3, 1, 1, 4, 3, 1, 1, 1, 0, 0, 2, 3, 1, 3, 1, 4, 2, 2, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 6, 3, 1, 1, 1 ); protected function initReduceCallbacks() { $this->reduceCallbacks = [ 0 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 1 => function ($stackPos) { $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); }, 2 => function ($stackPos) { if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; }, 3 => function ($stackPos) { $this->semValue = array(); }, 4 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 5 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 6 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 7 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 8 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 9 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 10 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 11 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 12 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 13 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 14 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 15 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 16 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 17 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 18 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 19 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 20 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 21 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 22 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 23 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 24 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 25 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 26 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 27 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 28 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 29 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 30 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 31 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 32 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 33 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 34 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 35 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 36 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 37 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 38 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 39 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 40 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 41 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 42 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 43 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 44 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 45 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 46 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 47 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 48 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 49 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 50 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 51 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 52 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 53 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 54 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 55 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 56 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 57 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 58 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 59 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 60 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 61 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 62 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 63 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 64 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 65 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 66 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 67 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 68 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 69 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 70 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 71 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 72 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 73 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 74 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 75 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 76 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 77 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 78 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 79 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 80 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 81 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 82 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 83 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 84 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 85 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 86 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 87 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 88 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 89 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 90 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 91 => function ($stackPos) { $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 92 => function ($stackPos) { $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 93 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 94 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 95 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 96 => function ($stackPos) { $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 97 => function ($stackPos) { $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($this->semValue); }, 98 => function ($stackPos) { $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 99 => function ($stackPos) { $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 100 => function ($stackPos) { $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 101 => function ($stackPos) { $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 102 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 103 => function ($stackPos) { $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 104 => function ($stackPos) { $this->semValue = Stmt\Use_::TYPE_FUNCTION; }, 105 => function ($stackPos) { $this->semValue = Stmt\Use_::TYPE_CONSTANT; }, 106 => function ($stackPos) { $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); }, 107 => function ($stackPos) { $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 108 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 109 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 110 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 111 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 112 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 113 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 114 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); }, 115 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); }, 116 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); }, 117 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); }, 118 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; }, 119 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; }, 120 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 121 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 122 => function ($stackPos) { $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 123 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 124 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 125 => function ($stackPos) { $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 126 => function ($stackPos) { if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; }, 127 => function ($stackPos) { $this->semValue = array(); }, 128 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 129 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 130 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 131 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 132 => function ($stackPos) { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 133 => function ($stackPos) { if ($this->semStack[$stackPos-(3-2)]) { $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; } else { $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; if (null === $this->semValue) { $this->semValue = array(); } } }, 134 => function ($stackPos) { $this->semValue = new Stmt\If_($this->semStack[$stackPos-(5-2)], ['stmts' => is_array($this->semStack[$stackPos-(5-3)]) ? $this->semStack[$stackPos-(5-3)] : array($this->semStack[$stackPos-(5-3)]), 'elseifs' => $this->semStack[$stackPos-(5-4)], 'else' => $this->semStack[$stackPos-(5-5)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 135 => function ($stackPos) { $this->semValue = new Stmt\If_($this->semStack[$stackPos-(8-2)], ['stmts' => $this->semStack[$stackPos-(8-4)], 'elseifs' => $this->semStack[$stackPos-(8-5)], 'else' => $this->semStack[$stackPos-(8-6)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); }, 136 => function ($stackPos) { $this->semValue = new Stmt\While_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 137 => function ($stackPos) { $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(5-4)], is_array($this->semStack[$stackPos-(5-2)]) ? $this->semStack[$stackPos-(5-2)] : array($this->semStack[$stackPos-(5-2)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 138 => function ($stackPos) { $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 139 => function ($stackPos) { $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 140 => function ($stackPos) { $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 141 => function ($stackPos) { $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 142 => function ($stackPos) { $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 143 => function ($stackPos) { $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 144 => function ($stackPos) { $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 145 => function ($stackPos) { $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 146 => function ($stackPos) { $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 147 => function ($stackPos) { $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 148 => function ($stackPos) { $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 149 => function ($stackPos) { $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 150 => function ($stackPos) { $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 151 => function ($stackPos) { $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 152 => function ($stackPos) { $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 153 => function ($stackPos) { $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); }, 154 => function ($stackPos) { $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 155 => function ($stackPos) { $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 156 => function ($stackPos) { $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); }, 157 => function ($stackPos) { $this->semValue = new Stmt\Throw_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 158 => function ($stackPos) { $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 159 => function ($stackPos) { $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 160 => function ($stackPos) { $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 161 => function ($stackPos) { $this->semValue = array(); /* means: no statement */ }, 162 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 163 => function ($stackPos) { $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ }, 164 => function ($stackPos) { $this->semValue = array(); }, 165 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 166 => function ($stackPos) { $this->semValue = new Stmt\Catch_(array($this->semStack[$stackPos-(8-3)]), $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); }, 167 => function ($stackPos) { $this->semValue = null; }, 168 => function ($stackPos) { $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 169 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 170 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 171 => function ($stackPos) { $this->semValue = false; }, 172 => function ($stackPos) { $this->semValue = true; }, 173 => function ($stackPos) { $this->semValue = false; }, 174 => function ($stackPos) { $this->semValue = true; }, 175 => function ($stackPos) { $this->semValue = false; }, 176 => function ($stackPos) { $this->semValue = true; }, 177 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 178 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 179 => function ($stackPos) { $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(10-3)], ['byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-5)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); }, 180 => function ($stackPos) { $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); $this->checkClass($this->semValue, $stackPos-(7-2)); }, 181 => function ($stackPos) { $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(6-2)], ['extends' => $this->semStack[$stackPos-(6-3)], 'stmts' => $this->semStack[$stackPos-(6-5)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkInterface($this->semValue, $stackPos-(6-2)); }, 182 => function ($stackPos) { $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(5-2)], ['stmts' => $this->semStack[$stackPos-(5-4)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 183 => function ($stackPos) { $this->semValue = 0; }, 184 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; }, 185 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_FINAL; }, 186 => function ($stackPos) { $this->semValue = null; }, 187 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 188 => function ($stackPos) { $this->semValue = array(); }, 189 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 190 => function ($stackPos) { $this->semValue = array(); }, 191 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 192 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 193 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 194 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 195 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 196 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 197 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 198 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 199 => function ($stackPos) { $this->semValue = null; }, 200 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 201 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 202 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 203 => function ($stackPos) { $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 204 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 205 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, 206 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 207 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(5-3)]; }, 208 => function ($stackPos) { $this->semValue = array(); }, 209 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 210 => function ($stackPos) { $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 211 => function ($stackPos) { $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 212 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 213 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 214 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 215 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 216 => function ($stackPos) { $this->semValue = array(); }, 217 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 218 => function ($stackPos) { $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(3-2)], is_array($this->semStack[$stackPos-(3-3)]) ? $this->semStack[$stackPos-(3-3)] : array($this->semStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 219 => function ($stackPos) { $this->semValue = array(); }, 220 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 221 => function ($stackPos) { $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 222 => function ($stackPos) { $this->semValue = null; }, 223 => function ($stackPos) { $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 224 => function ($stackPos) { $this->semValue = null; }, 225 => function ($stackPos) { $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 226 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)], false); }, 227 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(2-2)], true); }, 228 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)], false); }, 229 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 230 => function ($stackPos) { $this->semValue = array(); }, 231 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 232 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 233 => function ($stackPos) { $this->semValue = new Node\Param($this->semStack[$stackPos-(4-4)], null, $this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue); }, 234 => function ($stackPos) { $this->semValue = new Node\Param($this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-3)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue); }, 235 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 236 => function ($stackPos) { $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 237 => function ($stackPos) { $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 238 => function ($stackPos) { $this->semValue = null; }, 239 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 240 => function ($stackPos) { $this->semValue = null; }, 241 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 242 => function ($stackPos) { $this->semValue = array(); }, 243 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 244 => function ($stackPos) { $this->semValue = array(new Node\Arg($this->semStack[$stackPos-(3-2)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes)); }, 245 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 246 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 247 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 248 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 249 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 250 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 251 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 252 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 253 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 254 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 255 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 256 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 257 => function ($stackPos) { $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 258 => function ($stackPos) { $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 259 => function ($stackPos) { if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } }, 260 => function ($stackPos) { $this->semValue = array(); }, 261 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 262 => function ($stackPos) { $this->semValue = new Stmt\Property($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $stackPos-(3-1)); }, 263 => function ($stackPos) { $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(3-2)], 0, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 264 => function ($stackPos) { $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(9-4)], ['type' => $this->semStack[$stackPos-(9-1)], 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); $this->checkClassMethod($this->semValue, $stackPos-(9-1)); }, 265 => function ($stackPos) { $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 266 => function ($stackPos) { $this->semValue = array(); }, 267 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 268 => function ($stackPos) { $this->semValue = array(); }, 269 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 270 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 271 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 272 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 273 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 274 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 275 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 276 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 277 => function ($stackPos) { $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); }, 278 => function ($stackPos) { $this->semValue = null; }, 279 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 280 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 281 => function ($stackPos) { $this->semValue = 0; }, 282 => function ($stackPos) { $this->semValue = 0; }, 283 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 284 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 285 => function ($stackPos) { $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; }, 286 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; }, 287 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; }, 288 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; }, 289 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_STATIC; }, 290 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; }, 291 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_FINAL; }, 292 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 293 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 294 => function ($stackPos) { $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 295 => function ($stackPos) { $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 296 => function ($stackPos) { $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 297 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 298 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 299 => function ($stackPos) { $this->semValue = array(); }, 300 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 301 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 302 => function ($stackPos) { $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 303 => function ($stackPos) { $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 304 => function ($stackPos) { $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 305 => function ($stackPos) { $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 306 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 307 => function ($stackPos) { $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 308 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 309 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 310 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 311 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 312 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 313 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 314 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 315 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 316 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 317 => function ($stackPos) { $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 318 => function ($stackPos) { $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 319 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 320 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 321 => function ($stackPos) { $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 322 => function ($stackPos) { $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 323 => function ($stackPos) { $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 324 => function ($stackPos) { $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 325 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 326 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 327 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 328 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 329 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 330 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 331 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 332 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 333 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 334 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 335 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 336 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 337 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 338 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 339 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 340 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 341 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 342 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 343 => function ($stackPos) { $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 344 => function ($stackPos) { $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 345 => function ($stackPos) { $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 346 => function ($stackPos) { $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 347 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 348 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 349 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 350 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 351 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 352 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 353 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 354 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 355 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 356 => function ($stackPos) { $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 357 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 358 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 359 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 360 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 361 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 362 => function ($stackPos) { $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 363 => function ($stackPos) { $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 364 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 365 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 366 => function ($stackPos) { $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 367 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 368 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 369 => function ($stackPos) { $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 370 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); }, 371 => function ($stackPos) { $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 372 => function ($stackPos) { $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 373 => function ($stackPos) { $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 374 => function ($stackPos) { $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 375 => function ($stackPos) { $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 376 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); }, 377 => function ($stackPos) { $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 378 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 379 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 380 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 381 => function ($stackPos) { $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 382 => function ($stackPos) { $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 383 => function ($stackPos) { $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 384 => function ($stackPos) { $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 385 => function ($stackPos) { $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-4)], 'uses' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); }, 386 => function ($stackPos) { $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(11-3)], 'params' => $this->semStack[$stackPos-(11-5)], 'uses' => $this->semStack[$stackPos-(11-7)], 'returnType' => $this->semStack[$stackPos-(11-8)], 'stmts' => $this->semStack[$stackPos-(11-10)]], $this->startAttributeStack[$stackPos-(11-1)] + $this->endAttributes); }, 387 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 388 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 389 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 390 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 391 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); }, 392 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); }, 393 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 394 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch(Scalar\String_::fromString($this->semStack[$stackPos-(4-1)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes), $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 395 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 396 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 397 => function ($stackPos) { $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes), $this->semStack[$stackPos-(7-2)]); $this->checkClass($this->semValue[0], -1); }, 398 => function ($stackPos) { $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 399 => function ($stackPos) { list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 400 => function ($stackPos) { $this->semValue = array(); }, 401 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, 402 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 403 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 404 => function ($stackPos) { $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 405 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 406 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 407 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 408 => function ($stackPos) { $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 409 => function ($stackPos) { $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 410 => function ($stackPos) { $this->semValue = $this->fixupPhp5StaticPropCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 411 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 412 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 413 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 414 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 415 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 416 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 417 => function ($stackPos) { $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 418 => function ($stackPos) { $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 419 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 420 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 421 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 422 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 423 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 424 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 425 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 426 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 427 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 428 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 429 => function ($stackPos) { $this->semValue = null; }, 430 => function ($stackPos) { $this->semValue = null; }, 431 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 432 => function ($stackPos) { $this->semValue = array(); }, 433 => function ($stackPos) { $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`', false), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); }, 434 => function ($stackPos) { foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', false); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 435 => function ($stackPos) { $this->semValue = array(); }, 436 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 437 => function ($stackPos) { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, true); }, 438 => function ($stackPos) { $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 439 => function ($stackPos) { $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, false); }, 440 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 441 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 442 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 443 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 444 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 445 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 446 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 447 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 448 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], false); }, 449 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], false); }, 450 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 451 => function ($stackPos) { $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 452 => function ($stackPos) { $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 453 => function ($stackPos) { $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 454 => function ($stackPos) { $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 455 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 456 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 457 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 458 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 459 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 460 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 461 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 462 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 463 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 464 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 465 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 466 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 467 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 468 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 469 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 470 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 471 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 472 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 473 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 474 => function ($stackPos) { $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 475 => function ($stackPos) { $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 476 => function ($stackPos) { $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 477 => function ($stackPos) { $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 478 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 479 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 480 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 481 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 482 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 483 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 484 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 485 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 486 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 487 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 488 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 489 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 490 => function ($stackPos) { $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 491 => function ($stackPos) { $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 492 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 493 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 494 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); }, 495 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); }, 496 => function ($stackPos) { $this->semValue = array(); }, 497 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 498 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 499 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 500 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 501 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 502 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 503 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 504 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 505 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 506 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 507 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 508 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 509 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 510 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 511 => function ($stackPos) { $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 512 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 513 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 514 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 515 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 516 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 517 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 518 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 519 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 520 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 521 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 522 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 523 => function ($stackPos) { $var = substr($this->semStack[$stackPos-(1-1)], 1); $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; }, 524 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 525 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 526 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 527 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 528 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 529 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 530 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 531 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 532 => function ($stackPos) { $this->semValue = null; }, 533 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 534 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 535 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 536 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 537 => function ($stackPos) { $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; }, 538 => function ($stackPos) { $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 539 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 540 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 541 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 542 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 543 => function ($stackPos) { $this->semValue = null; }, 544 => function ($stackPos) { $this->semValue = array(); }, 545 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 546 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 547 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 548 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 549 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 550 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 551 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 552 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 553 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 554 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 555 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 556 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); }, 557 => function ($stackPos) { $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 558 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 559 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 560 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 561 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 562 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 563 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 564 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 565 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 566 => function ($stackPos) { $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 567 => function ($stackPos) { $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 568 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, ]; } } php-parser/lib/PhpParser/Parser/Php7.php000064400000527326150250175720014105 0ustar00'", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_READONLY", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_ENUM", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_NULLSAFE_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "T_ATTRIBUTE", "';'", "']'", "'{'", "'}'", "'('", "')'", "'`'", "'\"'", "'$'" ); protected $tokenToSymbol = array( 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 56, 166, 168, 167, 55, 168, 168, 163, 164, 53, 50, 8, 51, 52, 54, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 31, 159, 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 70, 168, 160, 36, 168, 165, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 161, 35, 162, 58, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158 ); protected $action = array( 132, 133, 134, 575, 135, 136, 0, 738, 739, 740, 137, 37, 850, 825, 851, 476,-32766,-32766,-32766,-32767, -32767,-32767,-32767, 101, 102, 103, 104, 105, 1097, 1098, 1099, 1096, 1095, 1094, 1100, 732, 731,-32766, 1289,-32766, -32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, -32767, 1022, 377, 376, 2, 741,-32766,-32766,-32766,-32766, -32766, 822, 417,-32766,-32766,-32766,-32766,-32766,-32766, 267, 138, 399, 745, 746, 747, 748, 287,-32766, 423,-32766, -32766,-32766,-32766,-32766,-32766, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 779, 576, 780, 781, 782, 783, 771, 772, 340, 341, 774, 775, 760, 761, 762, 764, 765, 766, 351, 806, 807, 808, 809, 810, 577, 767, 768, 578, 579, 800, 791, 789, 790, 803, 786, 787, -327, 423, 580, 581, 785, 582, 583, 584, 585, 586, 587, 605, -590, 477, -86, 814, 788, 588, 589, -590, 139,-32766,-32766,-32766, 132, 133, 134, 575, 135, 136, 1046, 738, 739, 740, 137, 37, 323, 1013, 823, 824, 1334, 1324,-32766, 1335,-32766,-32766,-32766,-32766, -32766,-32766,-32766, 1097, 1098, 1099, 1096, 1095, 1094, 1100, -587, 732, 731,-32766,-32766,-32766, 12, -587, 81,-32766, -32766,-32766, 945, 946, 322, 927, 34, 947, 1224, 1223, 1225, 741, -86, 942,-32766, 1075,-32766,-32766,-32766,-32766, -32766, 239,-32766,-32766,-32766, 267, 138, 399, 745, 746, 747, 748, 461, 462, 423, 35, 247, 103, 104, 105, 128, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 779, 576, 780, 781, 782, 783, 771, 772, 340, 341, 774, 775, 760, 761, 762, 764, 765, 766, 351, 806, 807, 808, 809, 810, 577, 767, 768, 578, 579, 800, 791, 789, 790, 803, 786, 787, -327, 144, 580, 581, 785, 582, 583, 584, 585, 586, 587, 1222, 82, 83, 84, -590, 788, 588, 589, -590, 148, 763, 733, 734, 735, 736, 737, 1309, 738, 739, 740, 776, 777, 36, 1308, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 288, 271, -587, -193, 375, 376, -587, 976,-32766, 1021, 453, 454, 455, 109, 417, 945, 946, 741, 712, 819, 947,-32766,-32766, -32766, -271, 1073, 941, 1224, 1223, 1225, 288, 742, 743, 744, 745, 746, 747, 748, -192, -365, 812, -365,-32766, 599,-32766,-32766, 549, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 779, 802, 780, 781, 782, 783, 771, 772, 773, 801, 774, 775, 760, 761, 762, 764, 765, 766, 805, 806, 807, 808, 809, 810, 811, 767, 768, 769, 770, 800, 791, 789, 790, 803, 786, 787, 251, 820, 778, 784, 785, 792, 793, 795, 794, 796, 797, 732, 731, 1261, 1022, 1019, 788, 799, 798, 49, 50, 51, 507, 52, 53, 1009, 1008, 1007, 1010, 54, 55, -111, 56, 816, 1045, 14, -111, 1022, -111, 287, 1305, 977, 306, 302, 1022, 238, -111, -111, -111, -111, -111, -111, -111, -111, 106, 107, 108, 1089, 271, -32766,-32766,-32766, 280, 284, 126, -193, 929, 57, 58, 287, 109, 1019, -541, 59, 308, 60, 244, 245, 61, 62, 63, 64, 65, 66, 67, 68, 1229, 27, 269, 69, 439, 508, -341, 1022, 929, 1255, 1256, 509, 907, 823, -192, 150, 907, 1253, 41, 24, 510, 352, 511, 818, 512, 386, 513, 11, 699, 514, 515, 648, 25, 814, 43, 44, 440, 372, 371, 907, 45, 516, 702, 1220, 667, 668, 363, 334, -540, 357, -541, -541, 320, 1215, 1249, 518, 519, 520, -581, 1074, 335, 724, -581, 1019,-32766, -541, 336, 521, 522, 703, 1243, 1244, 1245, 1246, 1240, 1241, 294, -541, 850, -547, 851, 823, 1247, 1242, 365, 1022, 1224, 1223, 1225, 295, -153, -153, -153, 369, 70, 897, 318, 319, 322, 897, 384, 149, 402, 373, 374, -153, 435, -153, 436, -153, 280, -153, -540, -540, 141, 1220, 378, 379, 639, 640, 322, 370, 897, 907, 437, 438, 829, -540, -88, 151, 732, 731, 945, 946, 153, 823,-32766, 517, -51, -540, 154, -546, 883, 941, -111, -111, -111, 31, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 155, 74, 27, 157, 32, 322, -85, 123, 124, 909, 129, 697, 130, 909, 823, 697, -153, 143, 1253, 158,-32766, -544, 1229, -542, 159, 160, 1222, 161, -79, 1134, 1136, -75, 285,-32766,-32766,-32766, 909,-32766, 697,-32766, -539,-32766, -301, -73,-32766, 897, -72, -71, 1220,-32766,-32766,-32766, -16, 140, 1215,-32766,-32766, 732, 731, 322, -70,-32766, 414, -69, -4, 907, -68, -67, 521, 522,-32766, 1243, 1244, 1245, 1246, 1240, 1241, -66, -47, -18, 147, 270, 281, 1247, 1242, -544, -544, -542, -542, 732, 731, 713, 716, 906,-32766, 72, 146, 907, 319, 322, 1222, -297, -542, 823, -539, -539, 276,-32766,-32766,-32766, 277,-32766, -544,-32766, -542,-32766, 282, 283,-32766, -539, 909, 328, 697,-32766,-32766,-32766,-32766, 704, 286,-32766,-32766, -539, 1222, 923, 289,-32766, 414, 1220, 290,-32766,-32766,-32766, 271,-32766,-32766,-32766, 47,-32766, 897, -111,-32766, 677, 109, 814, 145,-32766,-32766,-32766,-32766, 823, 131,-32766, -32766, 1336,-32766, 654, 670,-32766, 414, 1104, 370, 637, 430, 551, 73, 13,-32766, 293, 555, 295, 897, 945, 946, 649, 74, 434, 517, 458, 322, 487, 690, 842, 941, -111, -111, -111, 301, 1022, 561, 655, 671, 1260, 300,-32766, -539,-32766, 907, 603, 303, 1222, 296, 297, 39, 1262, 9, 40,-32766,-32766,-32766, 0,-32766, 907, -32766, 909,-32766, 697, -4,-32766, 0, 1229, 907, 0, -32766,-32766,-32766,-32766, 307, 125,-32766,-32766, 0, 1222, 907, 0,-32766, 414, 0, 0,-32766,-32766,-32766, 707, -32766,-32766,-32766, 962,-32766, 697, -505,-32766, 714, -495, 7, 482,-32766,-32766,-32766,-32766, -539, -539,-32766,-32766, 16, 1222, 567, 367,-32766, 414, 925, 295,-32766,-32766, -32766, -539,-32766,-32766,-32766, 822,-32766, 897, 721,-32766, 722, -575, 888, -539,-32766,-32766,-32766, 986, 963, 970, -32766,-32766, 897, -249, -249, -249,-32766, 414, 823, 370, 960, 897, 971, 886, 958,-32766, 1078, 1081, 718, 1082, 945, 946, 1079, 897, 1080, 517, 1086, 33, 1250, 834, 883, 941, -111, -111, -111, 27, 1275, 1293, 1327, -248, -248, -248, 1220, 642, 884, 370, 317, 823, 366, 698, 701, 1253, 1331, 705, -111, 706, 945, 946, 708, 709, 710, 517, 909,-32766, 697, -249, 883, 941, -111, -111, -111, 711, 715, 700, -509, 1333, 845, 909, 48, 697, -573, 1220, 844, 853, 295, 935, 909, 1215, 697, 74, 978, 852, 1332, 322, 934, 932, 933, 936, 909, 1206, 697, -248, 522, 916, 1243, 1244, 1245, 1246, 1240, 1241, 926, 914, 968, 969, 1330, 1287, 1247, 1242, 1276, 1294, -32766, 1300, 1303, 1191, -547, -546, 1222, -545, 72, -489, 1, 319, 322,-32766,-32766,-32766, 28,-32766, 29,-32766, 38,-32766, 298, 299,-32766, 42, 46, 71, 75,-32766, -32766,-32766, 76, 77, 78,-32766,-32766, 368, 79, 80, 142,-32766, 414, 152, 156, 243, 324, 352, 353, 127, -32766, -274, 354, 355, 356, 357, 358, 359, 360, 361, 362, 364, 431, 0, -272, -271, 18, 19, 20, 21, 23, 401, 478, 479, 486, 489, 490, 491, 492, 496, 497, 498, 505, 684, 1233, 1174, 1251, 1048, 1047, 1028, 0, 1210, 1024, -276, -103, 17, 22, 26, 292, 400, 596, 600, 628, 689, 1178, 1228, 1175, 1306, 0, 0, 1254, 0, 322 ); protected $actionCheck = array( 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, 12, 13, 106, 1, 108, 31, 9, 10, 11, 44, 45, 46, 47, 48, 49, 50, 51, 52, 116, 117, 118, 119, 120, 121, 122, 37, 38, 30, 1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 138, 106, 107, 8, 57, 9, 10, 11, 9, 10, 155, 116, 9, 10, 11, 9, 10, 11, 71, 72, 73, 74, 75, 76, 77, 163, 30, 80, 32, 33, 34, 35, 36, 30, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 8, 80, 136, 137, 138, 139, 140, 141, 142, 143, 144, 51, 1, 161, 31, 80, 150, 151, 152, 8, 154, 9, 10, 11, 2, 3, 4, 5, 6, 7, 164, 9, 10, 11, 12, 13, 70, 1, 82, 159, 80, 85, 30, 83, 32, 33, 34, 35, 36, 37, 38, 116, 117, 118, 119, 120, 121, 122, 1, 37, 38, 9, 10, 11, 8, 8, 161, 9, 10, 11, 117, 118, 167, 1, 8, 122, 155, 156, 157, 57, 97, 128, 30, 162, 32, 33, 34, 35, 30, 14, 32, 33, 34, 71, 72, 73, 74, 75, 76, 77, 134, 135, 80, 147, 148, 50, 51, 52, 8, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 164, 8, 136, 137, 138, 139, 140, 141, 142, 143, 144, 80, 9, 10, 11, 160, 150, 151, 152, 164, 154, 2, 3, 4, 5, 6, 7, 1, 9, 10, 11, 12, 13, 30, 8, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 30, 57, 160, 8, 106, 107, 164, 31, 9, 137, 129, 130, 131, 69, 116, 117, 118, 57, 161, 80, 122, 9, 10, 11, 164, 1, 128, 155, 156, 157, 30, 71, 72, 73, 74, 75, 76, 77, 8, 106, 80, 108, 30, 1, 32, 33, 85, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 8, 156, 136, 137, 138, 139, 140, 141, 142, 143, 144, 37, 38, 146, 138, 116, 150, 151, 152, 2, 3, 4, 5, 6, 7, 119, 120, 121, 122, 12, 13, 101, 15, 80, 1, 101, 106, 138, 108, 163, 1, 159, 8, 113, 138, 97, 116, 117, 118, 119, 120, 121, 122, 123, 53, 54, 55, 123, 57, 9, 10, 11, 163, 30, 14, 164, 122, 50, 51, 163, 69, 116, 70, 56, 8, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 1, 70, 71, 72, 73, 74, 162, 138, 122, 78, 79, 80, 1, 82, 164, 14, 1, 86, 87, 88, 89, 163, 91, 156, 93, 106, 95, 108, 161, 98, 99, 75, 76, 80, 103, 104, 105, 106, 107, 1, 109, 110, 31, 116, 75, 76, 115, 116, 70, 163, 134, 135, 8, 122, 1, 124, 125, 126, 160, 159, 8, 161, 164, 116, 137, 149, 8, 136, 137, 31, 139, 140, 141, 142, 143, 144, 145, 161, 106, 163, 108, 82, 151, 152, 8, 138, 155, 156, 157, 158, 75, 76, 77, 8, 163, 84, 165, 166, 167, 84, 8, 101, 102, 106, 107, 90, 8, 92, 8, 94, 163, 96, 134, 135, 161, 116, 106, 107, 111, 112, 167, 106, 84, 1, 8, 8, 8, 149, 31, 14, 37, 38, 117, 118, 14, 82, 137, 122, 31, 161, 14, 163, 127, 128, 129, 130, 131, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 14, 163, 70, 14, 14, 167, 31, 16, 16, 159, 16, 161, 16, 159, 82, 161, 162, 16, 86, 16, 74, 70, 1, 70, 16, 16, 80, 16, 31, 59, 60, 31, 37, 87, 88, 89, 159, 91, 161, 93, 70, 95, 35, 31, 98, 84, 31, 31, 116, 103, 104, 105, 31, 161, 122, 109, 110, 37, 38, 167, 31, 115, 116, 31, 0, 1, 31, 31, 136, 137, 124, 139, 140, 141, 142, 143, 144, 31, 31, 31, 31, 31, 31, 151, 152, 134, 135, 134, 135, 37, 38, 31, 31, 31, 74, 163, 31, 1, 166, 167, 80, 35, 149, 82, 134, 135, 35, 87, 88, 89, 35, 91, 161, 93, 161, 95, 35, 35, 98, 149, 159, 35, 161, 103, 104, 105, 74, 31, 37, 109, 110, 161, 80, 38, 37, 115, 116, 116, 37, 87, 88, 89, 57, 91, 124, 93, 70, 95, 84, 128, 98, 77, 69, 80, 70, 103, 104, 105, 137, 82, 31, 109, 110, 83, 85, 96, 94, 115, 116, 82, 106, 113, 108, 85, 154, 97, 124, 113, 89, 158, 84, 117, 118, 90, 163, 128, 122, 97, 167, 97, 92, 127, 128, 129, 130, 131, 133, 138, 153, 100, 100, 146, 132, 74, 70, 137, 1, 153, 114, 80, 134, 135, 159, 146, 150, 159, 87, 88, 89, -1, 91, 1, 93, 159, 95, 161, 162, 98, -1, 1, 1, -1, 103, 104, 105, 74, 132, 161, 109, 110, -1, 80, 1, -1, 115, 116, -1, -1, 87, 88, 89, 31, 91, 124, 93, 159, 95, 161, 149, 98, 31, 149, 149, 102, 103, 104, 105, 74, 134, 135, 109, 110, 149, 80, 81, 149, 115, 116, 154, 158, 87, 88, 89, 149, 91, 124, 93, 155, 95, 84, 159, 98, 159, 163, 159, 161, 103, 104, 105, 159, 159, 159, 109, 110, 84, 100, 101, 102, 115, 116, 82, 106, 159, 84, 159, 159, 159, 124, 159, 159, 162, 159, 117, 118, 159, 84, 159, 122, 159, 161, 160, 160, 127, 128, 129, 130, 131, 70, 160, 160, 160, 100, 101, 102, 116, 160, 162, 106, 161, 82, 161, 161, 161, 86, 162, 161, 128, 161, 117, 118, 161, 161, 161, 122, 159, 137, 161, 162, 127, 128, 129, 130, 131, 161, 161, 161, 165, 162, 162, 159, 70, 161, 163, 116, 162, 162, 158, 162, 159, 122, 161, 163, 162, 162, 162, 167, 162, 162, 162, 162, 159, 162, 161, 162, 137, 162, 139, 140, 141, 142, 143, 144, 162, 162, 162, 162, 162, 162, 151, 152, 162, 162, 74, 162, 162, 165, 163, 163, 80, 163, 163, 163, 163, 166, 167, 87, 88, 89, 163, 91, 163, 93, 163, 95, 134, 135, 98, 163, 163, 163, 163, 103, 104, 105, 163, 163, 163, 109, 110, 149, 163, 163, 163, 115, 116, 163, 163, 163, 163, 163, 163, 161, 124, 164, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, -1, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, -1, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, -1, -1, 166, -1, 167 ); protected $actionBase = array( 0, -2, 154, 542, 752, 893, 929, 580, 53, 394, 855, 307, 307, 67, 307, 307, 307, 565, 908, 908, 917, 908, 538, 784, 649, 649, 649, 708, 708, 708, 708, 740, 740, 849, 849, 881, 817, 634, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 12, 323, 389, 678, 1044, 1050, 1046, 1051, 1042, 1041, 1045, 1047, 1052, 942, 943, 753, 946, 947, 949, 950, 1048, 873, 1043, 1049, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 346, 491, 50, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 54, 54, 54, 620, 620, 359, 190, 184, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 658, 47, 144, 144, 7, 7, 7, 7, 7, 371, -25, -25, -25, -25, 709, 347, 916, 474, 526, 375, 280, 317, 245, 340, 340, 187, 187, 396, 396, -87, -87, 396, 396, 396, 747, 747, 747, 747, 443, 505, -94, 308, 454, 480, 480, 480, 480, 454, 454, 454, 454, 755, 1054, 454, 454, 454, 641, 822, 822, 998, 442, 442, 442, 822, 499, 776, 88, 499, 88, 37, 92, 756, 85, -54, 425, 756, 639, 764, 189, 143, 820, 524, 820, 1040, 385, 767, 413, 735, 688, 857, 902, 1053, 787, 940, 788, 941, 228, 98, 685, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1055, 415, 1040, 286, 1055, 1055, 1055, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 534, 286, 483, 496, 286, 774, 415, 12, 800, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 736, -16, 12, 323, 204, 204, 427, 168, 204, 204, 204, 204, 12, 12, 12, 524, 773, 733, 537, 742, 377, 773, 773, 773, 115, 124, 207, 342, 695, 754, 446, 761, 761, 775, 957, 957, 761, 765, 761, 775, 973, 761, 761, 957, 957, 809, 232, 625, 579, 612, 627, 957, 475, 761, 761, 761, 761, 792, 643, 761, 433, 281, 761, 761, 792, 758, 739, 46, 751, 957, 957, 957, 792, 603, 751, 751, 751, 819, 821, 746, 738, 571, 507, 645, 198, 783, 738, 738, 761, 619, 746, 738, 746, 738, 812, 738, 738, 738, 746, 738, 765, 585, 738, 691, 644, 188, 738, 6, 974, 975, 624, 979, 967, 980, 1009, 981, 985, 878, 956, 992, 972, 986, 965, 963, 750, 679, 680, 801, 797, 954, 771, 771, 771, 951, 771, 771, 771, 771, 771, 771, 771, 771, 679, 858, 814, 745, 777, 995, 682, 684, 743, 872, 899, 948, 994, 1030, 987, 741, 689, 1016, 999, 846, 875, 1000, 1001, 1017, 1031, 1032, 880, 772, 903, 904, 859, 1003, 879, 771, 974, 985, 663, 972, 986, 965, 963, 734, 724, 720, 723, 717, 704, 700, 703, 737, 1033, 907, 818, 866, 1002, 952, 679, 867, 1012, 856, 1018, 1019, 877, 778, 768, 868, 910, 1004, 1005, 1006, 882, 1034, 884, 744, 1013, 997, 1020, 780, 911, 1021, 1022, 1023, 1024, 887, 913, 888, 889, 823, 781, 1010, 757, 918, 528, 769, 770, 789, 1008, 642, 993, 900, 919, 920, 1025, 1026, 1027, 922, 923, 990, 828, 1014, 760, 1015, 1011, 829, 830, 647, 785, 1035, 759, 763, 779, 653, 674, 924, 925, 927, 991, 748, 762, 841, 843, 1037, 683, 1038, 931, 677, 844, 696, 938, 1029, 697, 699, 786, 901, 811, 782, 766, 1007, 749, 845, 939, 847, 848, 850, 1028, 853, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 458, 458, 458, 458, 458, 458, 307, 307, 307, 307, 0, 0, 307, 0, 0, 0, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 219, 219, 291, 291, 291, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 0, 291, 291, 291, 291, 291, 291, 291, 291, 809, 442, 442, 442, 442, 219, 219, 219, 219, 219, -88, -88, 219, 809, 219, 219, 442, 442, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 0, 0, 286, 88, 219, 765, 765, 765, 765, 219, 219, 219, 219, 88, 88, 219, 219, 219, 0, 0, 0, 0, 0, 0, 0, 0, 286, 88, 0, 286, 0, 765, 765, 219, 0, 809, 314, 219, 0, 0, 0, 0, 286, 765, 286, 415, 761, 88, 761, 415, 415, 204, 12, 314, 527, 527, 527, 527, 0, 0, 524, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 765, 0, 809, 0, 765, 765, 765, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 765, 0, 0, 957, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 973, 0, 0, 0, 0, 0, 0, 765, 0, 0, 0, 0, 0, 0, 0, 0, 771, 778, 0, 778, 0, 771, 771, 771, 0, 0, 0, 0, 785, 683 ); protected $actionDefault = array( 3,32767, 103,32767,32767,32767,32767,32767,32767,32767, 32767,32767, 101,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 593, 593, 593, 593,32767,32767, 253, 103,32767,32767, 467, 385, 385, 385,32767,32767, 537, 537, 537, 537, 537, 537,32767, 32767,32767,32767,32767,32767, 467,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767, 101,32767, 32767,32767, 37, 7, 8, 10, 11, 50, 17, 323, 32767,32767,32767,32767, 103,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767, 586,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 471, 450, 451, 453, 454, 384, 538, 592, 326, 589, 383, 146, 338, 328, 241, 329, 257, 472, 258, 473, 476, 477, 214, 286, 380, 150, 414, 468, 416, 466, 470, 415, 390, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 388, 389, 469, 447, 446, 445,32767,32767, 412, 413, 417,32767,32767,32767,32767,32767,32767,32767, 32767, 103,32767, 387, 420, 418, 419, 436, 437, 434, 435, 438,32767, 439, 440, 441, 442,32767, 315,32767, 32767,32767, 364, 362, 315, 112,32767,32767, 427, 428, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 531, 444,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 103,32767, 101, 533, 409, 411, 501, 422, 423, 421, 391,32767, 508,32767, 103, 510,32767,32767,32767,32767,32767,32767,32767, 532, 32767, 539, 539,32767, 494, 101, 194,32767,32767,32767, 194, 194,32767,32767,32767,32767,32767,32767,32767,32767, 600, 494, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,32767, 194, 111,32767,32767,32767, 101, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 189,32767, 267, 269, 103, 554, 194,32767, 513,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767, 506, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767, 494, 432, 139,32767, 139, 539, 424, 425, 426, 496, 539, 539, 539, 311, 288,32767, 32767,32767,32767, 511, 511, 101, 101, 101, 101, 506, 32767,32767,32767,32767, 112, 100, 100, 100, 100, 100, 104, 102,32767,32767,32767,32767, 222, 100,32767, 102, 102,32767,32767, 222, 224, 211, 102, 226,32767, 558, 559, 222, 102, 226, 226, 226, 246, 246, 483, 317, 102, 100, 102, 102, 196, 317, 317,32767, 102, 483, 317, 483, 317, 198, 317, 317, 317, 483, 317,32767, 102, 317, 213, 100, 100, 317,32767,32767,32767, 496, 32767,32767,32767,32767,32767,32767,32767, 221,32767,32767, 32767,32767,32767,32767,32767, 526,32767, 543, 556, 430, 431, 433, 541, 455, 456, 457, 458, 459, 460, 461, 463, 588,32767, 500,32767,32767,32767,32767, 337, 598, 32767, 598,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 599,32767, 539, 32767,32767,32767,32767, 429, 9, 76, 489, 43, 44, 52, 58, 517, 518, 519, 520, 514, 515, 521, 516, 32767,32767, 522, 564,32767,32767, 540, 591,32767,32767, 32767,32767,32767,32767, 139,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 526,32767, 137,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 539,32767,32767,32767,32767, 313, 310,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767, 539,32767,32767,32767,32767,32767, 290, 32767, 307,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767, 285,32767, 32767, 379,32767,32767,32767,32767, 358,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 152, 152, 3, 3, 340, 152, 152, 152, 340, 340, 152, 340, 340, 340, 152, 152, 152, 152, 152, 152, 279, 184, 261, 264, 246, 246, 152, 350, 152 ); protected $goto = array( 194, 194, 685, 425, 653, 346, 614, 650, 419, 310, 311, 331, 569, 316, 424, 332, 426, 630, 1200, 930, 693, 1051, 1201, 1204, 931, 1205, 165, 165, 165, 165, 218, 195, 191, 191, 175, 177, 213, 191, 191, 191, 191, 191, 192, 192, 192, 192, 192, 192, 186, 187, 188, 189, 190, 215, 213, 216, 529, 530, 415, 531, 533, 534, 535, 536, 537, 538, 539, 540, 1120, 166, 167, 168, 193, 169, 170, 171, 164, 172, 173, 174, 176, 212, 214, 217, 235, 240, 241, 242, 254, 255, 256, 257, 258, 259, 260, 261, 263, 264, 265, 266, 278, 279, 313, 314, 315, 420, 421, 422, 574, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 178, 234, 179, 196, 197, 198, 236, 186, 187, 188, 189, 190, 215, 1120, 199, 180, 181, 182, 200, 196, 183, 237, 201, 199, 163, 202, 203, 184, 204, 205, 206, 185, 207, 208, 209, 210, 211, 275, 275, 275, 275, 843, 593, 646, 647, 560, 664, 665, 666, 720, 629, 631, 840, 418, 651, 604, 841, 350, 675, 679, 996, 683, 691, 992, 616, 616, 817, 350, 350, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1252, 1092, 1093, 350, 350, 874, 350, 848, 1337, 896, 891, 892, 905, 849, 893, 846, 894, 895, 847, 548, 900, 899, 901, 350, 391, 394, 554, 594, 598, 1270, 1270, 1072, 1068, 1069, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1268, 1268, 815, 347, 348, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1221, 1020, 1221, 1020, 1221, 836, 5, 1020, 6, 1020, 1020, 1281, 961, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 349, 349, 349, 349, 1221, 460, 460, 566, 678, 1221, 1221, 1221, 1221, 344, 460, 1221, 1221, 1221, 1302, 1302, 1302, 1302, 602, 617, 620, 621, 622, 623, 643, 644, 645, 695, 836, 912, 553, 546, 1310, 913, 548, 532, 532, 821, 856, 982, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 543, 473, 543, 868, 543, 928, 855, 928, 389, 475, 337, 546, 553, 562, 563, 339, 572, 595, 609, 610, 1320, 1320, 249, 249, 1026, 1025, 15, 821, 450, 821, 494, 565, 495, 955, 955, 955, 955, 1320, 501, 450, 949, 956, 839, 652, 1321, 1321, 1169, 1214, 246, 246, 246, 246, 248, 250, 1323, 985, 959, 959, 957, 959, 719, 1321, 545, 994, 989, 470, 1295, 1296, 953, 405, 692, 917, 1108, 432, 541, 541, 541, 541, 612, 597, 452, 444, 1029, 1030, 1001, 658, 444, 1292, 444, 1292, 674, 1292, 860, 833, 656, 980, 836, 861, 547, 557, 854, 321, 305, 547, 333, 557, 1297, 1298, 392, 456, 570, 607, 1211, 944, 398, 858, 1304, 1304, 1304, 1304, 463, 573, 464, 465, 608, 1004, 866, 403, 404, 1328, 1329, 1057, 662, 1212, 663, 471, 407, 408, 409, 723, 676, 870, 1288, 410, 624, 626, 627, 342, 427, 1216, 869, 857, 1056, 1060, 427, 864, 1061, 1103, 966, 0, 0, 964, 1027, 1027, 0, 0, 0, 657, 1038, 1034, 1035, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, 0, 1059, 444, 954, 0, 1290, 1290, 1059, 592, 1085, 0, 696, 682, 682, 0, 502, 688, 1083, 0, 0, 0, 1217, 1218, 272, 428, 1101, 873, 0, 544, 831, 544, 0, 0, 0, 673, 938, 0, 0, 1015, 1031, 1032, 0, 0, 0, 0, 0, 0, 1219, 1278, 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 999, 999 ); protected $gotoCheck = array( 42, 42, 72, 65, 65, 96, 55, 55, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 78, 78, 9, 126, 78, 78, 78, 78, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 23, 23, 23, 23, 15, 129, 85, 85, 48, 85, 85, 85, 48, 48, 48, 26, 13, 48, 13, 27, 14, 48, 48, 48, 48, 48, 48, 107, 107, 7, 14, 14, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 143, 143, 14, 14, 45, 14, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 64, 15, 64, 14, 58, 58, 58, 58, 58, 168, 168, 15, 15, 15, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 169, 169, 6, 96, 96, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 72, 72, 72, 72, 72, 22, 46, 72, 46, 72, 72, 14, 49, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 24, 24, 24, 24, 72, 148, 148, 170, 14, 72, 72, 72, 72, 177, 148, 72, 72, 72, 9, 9, 9, 9, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 22, 72, 75, 75, 179, 72, 14, 171, 171, 12, 35, 102, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 19, 83, 19, 35, 19, 9, 35, 9, 61, 83, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 180, 180, 5, 5, 117, 117, 75, 12, 19, 12, 154, 103, 154, 19, 19, 19, 19, 180, 154, 19, 19, 19, 25, 63, 181, 181, 150, 14, 5, 5, 5, 5, 5, 5, 180, 25, 25, 25, 25, 25, 25, 181, 25, 25, 25, 174, 174, 174, 92, 92, 92, 17, 17, 112, 106, 106, 106, 106, 17, 106, 82, 23, 118, 118, 17, 119, 23, 129, 23, 129, 115, 129, 17, 18, 17, 17, 22, 39, 9, 9, 17, 167, 167, 9, 29, 9, 176, 176, 9, 9, 2, 2, 17, 91, 28, 37, 129, 129, 129, 129, 9, 9, 9, 9, 79, 109, 9, 81, 81, 9, 9, 128, 81, 159, 81, 156, 81, 81, 81, 98, 81, 41, 129, 81, 84, 84, 84, 81, 116, 20, 16, 16, 16, 16, 116, 9, 131, 146, 95, -1, -1, 16, 116, 116, -1, -1, -1, 116, 116, 116, 116, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, -1, 129, 23, 16, -1, 129, 129, 129, 8, 8, -1, 8, 8, 8, -1, 8, 8, 8, -1, -1, -1, 20, 20, 24, 88, 16, 16, -1, 24, 20, 24, -1, -1, -1, 88, 88, -1, -1, 88, 88, 88, -1, -1, -1, -1, -1, -1, 20, 20, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 106, 106 ); protected $gotoBase = array( 0, 0, -250, 0, 0, 360, 235, 181, 522, 7, 0, 0, 33, -156, -113, -178, 43, -49, 126, 72, 100, 0, -9, 158, 282, 377, 172, 176, 120, 150, 0, 0, 0, 0, 0, -39, 0, 119, 0, 116, 0, 45, -1, 0, 0, 195, -456, 0, -529, 250, 0, 0, 0, 0, 0, -33, 0, 0, 182, 0, 0, 306, 0, 143, 203, -235, 0, 0, 0, 0, 0, 0, -6, 0, 0, -21, 0, 0, -385, 124, -46, -19, 144, -123, 10, -538, 0, 0, 275, 0, 0, 127, 106, 0, 0, 60, -472, 0, 76, 0, 0, 0, 294, 328, 0, 0, 386, -50, 0, 99, 0, 0, 138, 0, 0, 149, 219, 87, 139, 137, 0, 0, 0, 0, 0, 0, 19, 0, 101, 159, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -69, 0, 0, 58, 0, 257, 0, 114, 0, 0, 0, -120, 0, 40, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 122, -7, 8, 264, 86, 0, 0, 107, 0, 78, 269, 0, 291, 55, 79, 0, 0 ); protected $gotoDefault = array( -32768, 506, 727, 4, 728, 921, 804, 813, 590, 523, 694, 343, 618, 416, 1286, 898, 1107, 571, 832, 1230, 1238, 451, 835, 326, 717, 880, 881, 882, 395, 381, 387, 393, 641, 619, 488, 867, 447, 859, 480, 862, 446, 871, 162, 413, 504, 875, 3, 877, 550, 908, 382, 885, 383, 669, 887, 556, 889, 890, 390, 396, 397, 1112, 564, 615, 902, 253, 558, 903, 380, 904, 911, 385, 388, 680, 459, 499, 493, 406, 1087, 559, 601, 638, 441, 467, 613, 625, 611, 474, 1023, 411, 325, 943, 951, 481, 457, 965, 345, 973, 725, 1119, 632, 483, 981, 633, 988, 991, 524, 525, 472, 1003, 268, 1006, 484, 1044, 659, 1017, 1018, 660, 634, 1040, 635, 661, 636, 1042, 466, 591, 1050, 448, 1058, 1274, 449, 1062, 262, 1065, 274, 412, 429, 1070, 1071, 8, 1077, 686, 687, 10, 273, 503, 1102, 681, 445, 1118, 433, 1188, 1190, 552, 485, 1208, 1207, 672, 500, 1213, 442, 1277, 443, 526, 468, 312, 527, 304, 329, 309, 542, 291, 330, 528, 469, 1283, 1291, 327, 30, 1311, 1322, 338, 568, 606 ); protected $ruleToNonTerminal = array( 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18, 21, 21, 22, 23, 23, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 30, 30, 32, 34, 34, 28, 36, 36, 33, 38, 38, 35, 35, 37, 37, 39, 39, 31, 40, 40, 41, 43, 44, 44, 45, 46, 46, 48, 47, 47, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 25, 25, 68, 68, 71, 71, 70, 69, 69, 62, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 26, 26, 27, 27, 27, 27, 27, 87, 87, 89, 89, 82, 82, 90, 90, 91, 91, 91, 83, 83, 86, 86, 84, 84, 92, 93, 93, 56, 56, 64, 64, 67, 67, 67, 66, 94, 94, 95, 57, 57, 57, 57, 96, 96, 97, 97, 98, 98, 99, 100, 100, 101, 101, 102, 102, 54, 54, 50, 50, 104, 52, 52, 105, 51, 51, 53, 53, 63, 63, 63, 63, 80, 80, 108, 108, 110, 110, 111, 111, 111, 111, 109, 109, 109, 113, 113, 113, 113, 88, 88, 116, 116, 116, 117, 117, 114, 114, 118, 118, 120, 120, 121, 121, 115, 122, 122, 119, 123, 123, 123, 123, 112, 112, 81, 81, 81, 20, 20, 20, 125, 124, 124, 126, 126, 126, 126, 59, 127, 127, 128, 60, 130, 130, 131, 131, 132, 132, 85, 133, 133, 133, 133, 133, 133, 138, 138, 139, 139, 140, 140, 140, 140, 140, 141, 142, 142, 137, 137, 134, 134, 136, 136, 144, 144, 143, 143, 143, 143, 143, 143, 143, 135, 145, 145, 147, 146, 146, 61, 103, 148, 148, 55, 55, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 155, 149, 149, 154, 154, 157, 158, 158, 159, 160, 161, 161, 161, 161, 19, 19, 72, 72, 72, 72, 150, 150, 150, 150, 163, 163, 151, 151, 153, 153, 153, 156, 156, 168, 168, 168, 168, 168, 168, 168, 168, 168, 169, 169, 107, 171, 171, 171, 171, 152, 152, 152, 152, 152, 152, 152, 152, 58, 58, 166, 166, 166, 166, 172, 172, 162, 162, 162, 173, 173, 173, 173, 173, 173, 73, 73, 65, 65, 65, 65, 129, 129, 129, 129, 176, 175, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 174, 174, 174, 174, 106, 170, 178, 178, 177, 177, 179, 179, 179, 179, 179, 179, 179, 179, 167, 167, 167, 167, 181, 182, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183 ); protected $ruleToLength = array( 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, 2, 0, 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, 2, 3, 1, 1, 7, 6, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, 3, 1, 2, 5, 7, 9, 6, 5, 6, 3, 2, 1, 1, 1, 0, 2, 1, 3, 8, 0, 4, 2, 1, 3, 0, 1, 0, 1, 0, 1, 3, 1, 1, 1, 8, 9, 7, 8, 7, 6, 8, 0, 2, 0, 2, 1, 2, 1, 2, 1, 1, 1, 0, 2, 0, 2, 0, 2, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 2, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 7, 0, 2, 1, 3, 3, 4, 1, 4, 0, 2, 5, 0, 2, 6, 0, 2, 0, 3, 1, 2, 1, 1, 2, 0, 1, 3, 0, 2, 1, 1, 1, 1, 6, 8, 6, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 1, 1, 2, 1, 1, 0, 1, 0, 2, 2, 2, 4, 3, 1, 1, 3, 1, 2, 2, 3, 2, 3, 1, 1, 2, 3, 1, 1, 3, 2, 0, 1, 5, 5, 10, 3, 5, 1, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 3, 2, 2, 3, 1, 0, 1, 1, 3, 3, 3, 4, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 1, 2, 4, 2, 2, 8, 9, 8, 9, 9, 10, 9, 10, 8, 3, 2, 0, 4, 2, 1, 3, 2, 1, 2, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 3, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 4, 1, 1, 3, 1, 1, 1, 1, 1, 3, 2, 3, 0, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 4, 4, 1, 4, 4, 0, 1, 1, 1, 3, 3, 1, 4, 2, 2, 1, 3, 1, 4, 4, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 1, 4, 1, 1, 1, 3, 1, 1, 2, 1, 3, 4, 3, 2, 0, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 3, 6, 3, 1, 1, 2, 1 ); protected function initReduceCallbacks() { $this->reduceCallbacks = [ 0 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 1 => function ($stackPos) { $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); }, 2 => function ($stackPos) { if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; }, 3 => function ($stackPos) { $this->semValue = array(); }, 4 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 5 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 6 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 7 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 8 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 9 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 10 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 11 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 12 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 13 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 14 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 15 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 16 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 17 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 18 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 19 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 20 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 21 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 22 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 23 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 24 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 25 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 26 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 27 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 28 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 29 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 30 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 31 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 32 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 33 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 34 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 35 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 36 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 37 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 38 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 39 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 40 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 41 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 42 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 43 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 44 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 45 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 46 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 47 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 48 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 49 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 50 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 51 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 52 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 53 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 54 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 55 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 56 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 57 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 58 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 59 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 60 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 61 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 62 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 63 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 64 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 65 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 66 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 67 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 68 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 69 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 70 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 71 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 72 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 73 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 74 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 75 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 76 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 77 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 78 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 79 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 80 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 81 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 82 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 83 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 84 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 85 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 86 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 87 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 88 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 89 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 90 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 91 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 92 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 93 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 94 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 95 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 96 => function ($stackPos) { $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 97 => function ($stackPos) { $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 98 => function ($stackPos) { /* nothing */ }, 99 => function ($stackPos) { /* nothing */ }, 100 => function ($stackPos) { /* nothing */ }, 101 => function ($stackPos) { $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); }, 102 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 103 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 104 => function ($stackPos) { $this->semValue = new Node\Attribute($this->semStack[$stackPos-(1-1)], [], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 105 => function ($stackPos) { $this->semValue = new Node\Attribute($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 106 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 107 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 108 => function ($stackPos) { $this->semValue = new Node\AttributeGroup($this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 109 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 110 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 111 => function ($stackPos) { $this->semValue = []; }, 112 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 113 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 114 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 115 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 116 => function ($stackPos) { $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 117 => function ($stackPos) { $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($this->semValue); }, 118 => function ($stackPos) { $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 119 => function ($stackPos) { $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 120 => function ($stackPos) { $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 121 => function ($stackPos) { $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 122 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 123 => function ($stackPos) { $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 124 => function ($stackPos) { $this->semValue = Stmt\Use_::TYPE_FUNCTION; }, 125 => function ($stackPos) { $this->semValue = Stmt\Use_::TYPE_CONSTANT; }, 126 => function ($stackPos) { $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); }, 127 => function ($stackPos) { $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 128 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 129 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 130 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 131 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 132 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 133 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 134 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 135 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 136 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 137 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); }, 138 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); }, 139 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); }, 140 => function ($stackPos) { $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); }, 141 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; }, 142 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; }, 143 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 144 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 145 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 146 => function ($stackPos) { $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 147 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 148 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 149 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 150 => function ($stackPos) { $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 151 => function ($stackPos) { if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; }, 152 => function ($stackPos) { $this->semValue = array(); }, 153 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 154 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 155 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 156 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 157 => function ($stackPos) { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 158 => function ($stackPos) { if ($this->semStack[$stackPos-(3-2)]) { $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; } else { $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; if (null === $this->semValue) { $this->semValue = array(); } } }, 159 => function ($stackPos) { $this->semValue = new Stmt\If_($this->semStack[$stackPos-(7-3)], ['stmts' => is_array($this->semStack[$stackPos-(7-5)]) ? $this->semStack[$stackPos-(7-5)] : array($this->semStack[$stackPos-(7-5)]), 'elseifs' => $this->semStack[$stackPos-(7-6)], 'else' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); }, 160 => function ($stackPos) { $this->semValue = new Stmt\If_($this->semStack[$stackPos-(10-3)], ['stmts' => $this->semStack[$stackPos-(10-6)], 'elseifs' => $this->semStack[$stackPos-(10-7)], 'else' => $this->semStack[$stackPos-(10-8)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); }, 161 => function ($stackPos) { $this->semValue = new Stmt\While_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 162 => function ($stackPos) { $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(7-5)], is_array($this->semStack[$stackPos-(7-2)]) ? $this->semStack[$stackPos-(7-2)] : array($this->semStack[$stackPos-(7-2)]), $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); }, 163 => function ($stackPos) { $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 164 => function ($stackPos) { $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 165 => function ($stackPos) { $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 166 => function ($stackPos) { $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 167 => function ($stackPos) { $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 168 => function ($stackPos) { $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 169 => function ($stackPos) { $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 170 => function ($stackPos) { $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 171 => function ($stackPos) { $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 172 => function ($stackPos) { $e = $this->semStack[$stackPos-(2-1)]; if ($e instanceof Expr\Throw_) { // For backwards-compatibility reasons, convert throw in statement position into // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). $this->semValue = new Stmt\Throw_($e->expr, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); } else { $this->semValue = new Stmt\Expression($e, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); } }, 173 => function ($stackPos) { $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 174 => function ($stackPos) { $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); }, 175 => function ($stackPos) { $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 176 => function ($stackPos) { $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(6-3)], new Expr\Error($this->startAttributeStack[$stackPos-(6-4)] + $this->endAttributeStack[$stackPos-(6-4)]), ['stmts' => $this->semStack[$stackPos-(6-6)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 177 => function ($stackPos) { $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 178 => function ($stackPos) { $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); }, 179 => function ($stackPos) { $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 180 => function ($stackPos) { $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 181 => function ($stackPos) { $this->semValue = array(); /* means: no statement */ }, 182 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 183 => function ($stackPos) { $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ }, 184 => function ($stackPos) { $this->semValue = array(); }, 185 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 186 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 187 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 188 => function ($stackPos) { $this->semValue = new Stmt\Catch_($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); }, 189 => function ($stackPos) { $this->semValue = null; }, 190 => function ($stackPos) { $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 191 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 192 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 193 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 194 => function ($stackPos) { $this->semValue = false; }, 195 => function ($stackPos) { $this->semValue = true; }, 196 => function ($stackPos) { $this->semValue = false; }, 197 => function ($stackPos) { $this->semValue = true; }, 198 => function ($stackPos) { $this->semValue = false; }, 199 => function ($stackPos) { $this->semValue = true; }, 200 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 201 => function ($stackPos) { $this->semValue = []; }, 202 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 203 => function ($stackPos) { $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 204 => function ($stackPos) { $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(8-3)], ['byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-5)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); }, 205 => function ($stackPos) { $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(9-4)], ['byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 206 => function ($stackPos) { $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); $this->checkClass($this->semValue, $stackPos-(7-2)); }, 207 => function ($stackPos) { $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(8-3)], ['type' => $this->semStack[$stackPos-(8-2)], 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); $this->checkClass($this->semValue, $stackPos-(8-3)); }, 208 => function ($stackPos) { $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(7-3)], ['extends' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => $this->semStack[$stackPos-(7-1)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); $this->checkInterface($this->semValue, $stackPos-(7-3)); }, 209 => function ($stackPos) { $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(6-3)], ['stmts' => $this->semStack[$stackPos-(6-5)], 'attrGroups' => $this->semStack[$stackPos-(6-1)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 210 => function ($stackPos) { $this->semValue = new Stmt\Enum_($this->semStack[$stackPos-(8-3)], ['scalarType' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); $this->checkEnum($this->semValue, $stackPos-(8-3)); }, 211 => function ($stackPos) { $this->semValue = null; }, 212 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 213 => function ($stackPos) { $this->semValue = null; }, 214 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 215 => function ($stackPos) { $this->semValue = 0; }, 216 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 217 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 218 => function ($stackPos) { $this->checkClassModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; }, 219 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; }, 220 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_FINAL; }, 221 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_READONLY; }, 222 => function ($stackPos) { $this->semValue = null; }, 223 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 224 => function ($stackPos) { $this->semValue = array(); }, 225 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 226 => function ($stackPos) { $this->semValue = array(); }, 227 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 228 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 229 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 230 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 231 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 232 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 233 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 234 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 235 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 236 => function ($stackPos) { $this->semValue = null; }, 237 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 238 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 239 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 240 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 241 => function ($stackPos) { $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 242 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 243 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, 244 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 245 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(5-3)]; }, 246 => function ($stackPos) { $this->semValue = array(); }, 247 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 248 => function ($stackPos) { $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 249 => function ($stackPos) { $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 250 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 251 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 252 => function ($stackPos) { $this->semValue = new Expr\Match_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); }, 253 => function ($stackPos) { $this->semValue = []; }, 254 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 255 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 256 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 257 => function ($stackPos) { $this->semValue = new Node\MatchArm($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 258 => function ($stackPos) { $this->semValue = new Node\MatchArm(null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 259 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, 260 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 261 => function ($stackPos) { $this->semValue = array(); }, 262 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 263 => function ($stackPos) { $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(5-3)], is_array($this->semStack[$stackPos-(5-5)]) ? $this->semStack[$stackPos-(5-5)] : array($this->semStack[$stackPos-(5-5)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 264 => function ($stackPos) { $this->semValue = array(); }, 265 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 266 => function ($stackPos) { $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->fixupAlternativeElse($this->semValue); }, 267 => function ($stackPos) { $this->semValue = null; }, 268 => function ($stackPos) { $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 269 => function ($stackPos) { $this->semValue = null; }, 270 => function ($stackPos) { $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->fixupAlternativeElse($this->semValue); }, 271 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)], false); }, 272 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(2-2)], true); }, 273 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)], false); }, 274 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)], false); }, 275 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 276 => function ($stackPos) { $this->semValue = array(); }, 277 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 278 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 279 => function ($stackPos) { $this->semValue = 0; }, 280 => function ($stackPos) { $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; }, 281 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; }, 282 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; }, 283 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; }, 284 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_READONLY; }, 285 => function ($stackPos) { $this->semValue = new Node\Param($this->semStack[$stackPos-(6-6)], null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); $this->checkParam($this->semValue); }, 286 => function ($stackPos) { $this->semValue = new Node\Param($this->semStack[$stackPos-(8-6)], $this->semStack[$stackPos-(8-8)], $this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-5)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes, $this->semStack[$stackPos-(8-2)], $this->semStack[$stackPos-(8-1)]); $this->checkParam($this->semValue); }, 287 => function ($stackPos) { $this->semValue = new Node\Param(new Expr\Error($this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes), null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); }, 288 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 289 => function ($stackPos) { $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 290 => function ($stackPos) { $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 291 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 292 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 293 => function ($stackPos) { $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 294 => function ($stackPos) { $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]); }, 295 => function ($stackPos) { $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 296 => function ($stackPos) { $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 297 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 298 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 299 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 300 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 301 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 302 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 303 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 304 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 305 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 306 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 307 => function ($stackPos) { $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 308 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 309 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 310 => function ($stackPos) { $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 311 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 312 => function ($stackPos) { $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 313 => function ($stackPos) { $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 314 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 315 => function ($stackPos) { $this->semValue = null; }, 316 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 317 => function ($stackPos) { $this->semValue = null; }, 318 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, 319 => function ($stackPos) { $this->semValue = null; }, 320 => function ($stackPos) { $this->semValue = array(); }, 321 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 322 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-2)]); }, 323 => function ($stackPos) { $this->semValue = new Node\VariadicPlaceholder($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 324 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 325 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 326 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 327 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 328 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 329 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(3-3)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->semStack[$stackPos-(3-1)]); }, 330 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 331 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 332 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 333 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 334 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 335 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 336 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 337 => function ($stackPos) { $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 338 => function ($stackPos) { $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 339 => function ($stackPos) { if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } }, 340 => function ($stackPos) { $this->semValue = array(); }, 341 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 342 => function ($stackPos) { $this->semValue = new Stmt\Property($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-1)]); $this->checkProperty($this->semValue, $stackPos-(5-2)); }, 343 => function ($stackPos) { $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-2)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-1)]); $this->checkClassConst($this->semValue, $stackPos-(5-2)); }, 344 => function ($stackPos) { $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(10-5)], ['type' => $this->semStack[$stackPos-(10-2)], 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-7)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); $this->checkClassMethod($this->semValue, $stackPos-(10-2)); }, 345 => function ($stackPos) { $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 346 => function ($stackPos) { $this->semValue = new Stmt\EnumCase($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-1)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 347 => function ($stackPos) { $this->semValue = null; /* will be skipped */ }, 348 => function ($stackPos) { $this->semValue = array(); }, 349 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 350 => function ($stackPos) { $this->semValue = array(); }, 351 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 352 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 353 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 354 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 355 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 356 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 357 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 358 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 359 => function ($stackPos) { $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); }, 360 => function ($stackPos) { $this->semValue = null; }, 361 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 362 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 363 => function ($stackPos) { $this->semValue = 0; }, 364 => function ($stackPos) { $this->semValue = 0; }, 365 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 366 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 367 => function ($stackPos) { $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; }, 368 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; }, 369 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; }, 370 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; }, 371 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_STATIC; }, 372 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; }, 373 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_FINAL; }, 374 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_READONLY; }, 375 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 376 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 377 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 378 => function ($stackPos) { $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 379 => function ($stackPos) { $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 380 => function ($stackPos) { $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 381 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 382 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 383 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 384 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 385 => function ($stackPos) { $this->semValue = array(); }, 386 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 387 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 388 => function ($stackPos) { $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 389 => function ($stackPos) { $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 390 => function ($stackPos) { $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 391 => function ($stackPos) { $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 392 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 393 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 394 => function ($stackPos) { $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 395 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 396 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 397 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 398 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 399 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 400 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 401 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 402 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 403 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 404 => function ($stackPos) { $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 405 => function ($stackPos) { $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 406 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 407 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 408 => function ($stackPos) { $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 409 => function ($stackPos) { $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 410 => function ($stackPos) { $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 411 => function ($stackPos) { $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 412 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 413 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 414 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 415 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 416 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 417 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 418 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 419 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 420 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 421 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 422 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 423 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 424 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 425 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 426 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 427 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 428 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 429 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 430 => function ($stackPos) { $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 431 => function ($stackPos) { $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 432 => function ($stackPos) { $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 433 => function ($stackPos) { $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 434 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 435 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 436 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 437 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 438 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 439 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 440 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 441 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 442 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 443 => function ($stackPos) { $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 444 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 445 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, 446 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 447 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 448 => function ($stackPos) { $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 449 => function ($stackPos) { $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 450 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 451 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 452 => function ($stackPos) { $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 453 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 454 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 455 => function ($stackPos) { $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 456 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); }, 457 => function ($stackPos) { $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 458 => function ($stackPos) { $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 459 => function ($stackPos) { $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 460 => function ($stackPos) { $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 461 => function ($stackPos) { $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 462 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); }, 463 => function ($stackPos) { $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 464 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 465 => function ($stackPos) { $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 466 => function ($stackPos) { $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 467 => function ($stackPos) { $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 468 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 469 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 470 => function ($stackPos) { $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 471 => function ($stackPos) { $this->semValue = new Expr\Throw_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 472 => function ($stackPos) { $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'returnType' => $this->semStack[$stackPos-(8-6)], 'expr' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); }, 473 => function ($stackPos) { $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 474 => function ($stackPos) { $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'uses' => $this->semStack[$stackPos-(8-6)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); }, 475 => function ($stackPos) { $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 476 => function ($stackPos) { $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 477 => function ($stackPos) { $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-8)], 'expr' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); }, 478 => function ($stackPos) { $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 479 => function ($stackPos) { $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'uses' => $this->semStack[$stackPos-(10-8)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); }, 480 => function ($stackPos) { $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes), $this->semStack[$stackPos-(8-3)]); $this->checkClass($this->semValue[0], -1); }, 481 => function ($stackPos) { $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 482 => function ($stackPos) { list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 483 => function ($stackPos) { $this->semValue = array(); }, 484 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, 485 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 486 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 487 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 488 => function ($stackPos) { $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 489 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 490 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 491 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 492 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 493 => function ($stackPos) { $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 494 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 495 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 496 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 497 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 498 => function ($stackPos) { $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 499 => function ($stackPos) { $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 500 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 501 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 502 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 503 => function ($stackPos) { $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; }, 504 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 505 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 506 => function ($stackPos) { $this->semValue = null; }, 507 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 508 => function ($stackPos) { $this->semValue = array(); }, 509 => function ($stackPos) { $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); }, 510 => function ($stackPos) { foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 511 => function ($stackPos) { $this->semValue = array(); }, 512 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 513 => function ($stackPos) { $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 514 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 515 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 516 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 517 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 518 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 519 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 520 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 521 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 522 => function ($stackPos) { $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 523 => function ($stackPos) { $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2; }, 524 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); }, 525 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); }, 526 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 527 => function ($stackPos) { $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 528 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); }, 529 => function ($stackPos) { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 530 => function ($stackPos) { $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 531 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 532 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 533 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 534 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); }, 535 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], true); }, 536 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); }, 537 => function ($stackPos) { $this->semValue = null; }, 538 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 539 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 540 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 541 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 542 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 543 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 544 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 545 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 546 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 547 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 548 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 549 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 550 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 551 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 552 => function ($stackPos) { $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 553 => function ($stackPos) { $this->semValue = new Expr\NullsafeMethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 554 => function ($stackPos) { $this->semValue = null; }, 555 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 556 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 557 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 558 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 559 => function ($stackPos) { $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 560 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 561 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 562 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 563 => function ($stackPos) { $this->semValue = new Expr\Variable(new Expr\Error($this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2; }, 564 => function ($stackPos) { $var = $this->semStack[$stackPos-(1-1)]->name; $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; }, 565 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 566 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 567 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 568 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 569 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 570 => function ($stackPos) { $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 571 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 572 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 573 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 574 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 575 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 576 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 577 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 578 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 579 => function ($stackPos) { $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; }, 580 => function ($stackPos) { $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 581 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); }, 582 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 583 => function ($stackPos) { /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */ }, 584 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 585 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 586 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 587 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 588 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 589 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 590 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 591 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 592 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 593 => function ($stackPos) { $this->semValue = null; }, 594 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 595 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 596 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 597 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); }, 598 => function ($stackPos) { $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 599 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 600 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 601 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 602 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 603 => function ($stackPos) { $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 604 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 605 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 606 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, 607 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 608 => function ($stackPos) { $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 609 => function ($stackPos) { $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 610 => function ($stackPos) { $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 611 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, ]; } } php-parser/lib/PhpParser/Parser/Multiple.php000064400000003164150250175720015047 0ustar00parsers = $parsers; } public function parse(string $code, ErrorHandler $errorHandler = null) { if (null === $errorHandler) { $errorHandler = new ErrorHandler\Throwing; } list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code); if ($firstError === null) { return $firstStmts; } for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) { list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code); if ($error === null) { return $stmts; } } throw $firstError; } private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) { $stmts = null; $error = null; try { $stmts = $parser->parse($code, $errorHandler); } catch (Error $error) {} return [$stmts, $error]; } } php-parser/lib/PhpParser/Parser/Tokens.php000064400000010036150250175720014513 0ustar00args($args) ); } /** * Creates a namespace builder. * * @param null|string|Node\Name $name Name of the namespace * * @return Builder\Namespace_ The created namespace builder */ public function namespace($name) : Builder\Namespace_ { return new Builder\Namespace_($name); } /** * Creates a class builder. * * @param string $name Name of the class * * @return Builder\Class_ The created class builder */ public function class(string $name) : Builder\Class_ { return new Builder\Class_($name); } /** * Creates an interface builder. * * @param string $name Name of the interface * * @return Builder\Interface_ The created interface builder */ public function interface(string $name) : Builder\Interface_ { return new Builder\Interface_($name); } /** * Creates a trait builder. * * @param string $name Name of the trait * * @return Builder\Trait_ The created trait builder */ public function trait(string $name) : Builder\Trait_ { return new Builder\Trait_($name); } /** * Creates an enum builder. * * @param string $name Name of the enum * * @return Builder\Enum_ The created enum builder */ public function enum(string $name) : Builder\Enum_ { return new Builder\Enum_($name); } /** * Creates a trait use builder. * * @param Node\Name|string ...$traits Trait names * * @return Builder\TraitUse The create trait use builder */ public function useTrait(...$traits) : Builder\TraitUse { return new Builder\TraitUse(...$traits); } /** * Creates a trait use adaptation builder. * * @param Node\Name|string|null $trait Trait name * @param Node\Identifier|string $method Method name * * @return Builder\TraitUseAdaptation The create trait use adaptation builder */ public function traitUseAdaptation($trait, $method = null) : Builder\TraitUseAdaptation { if ($method === null) { $method = $trait; $trait = null; } return new Builder\TraitUseAdaptation($trait, $method); } /** * Creates a method builder. * * @param string $name Name of the method * * @return Builder\Method The created method builder */ public function method(string $name) : Builder\Method { return new Builder\Method($name); } /** * Creates a parameter builder. * * @param string $name Name of the parameter * * @return Builder\Param The created parameter builder */ public function param(string $name) : Builder\Param { return new Builder\Param($name); } /** * Creates a property builder. * * @param string $name Name of the property * * @return Builder\Property The created property builder */ public function property(string $name) : Builder\Property { return new Builder\Property($name); } /** * Creates a function builder. * * @param string $name Name of the function * * @return Builder\Function_ The created function builder */ public function function(string $name) : Builder\Function_ { return new Builder\Function_($name); } /** * Creates a namespace/class use builder. * * @param Node\Name|string $name Name of the entity (namespace or class) to alias * * @return Builder\Use_ The created use builder */ public function use($name) : Builder\Use_ { return new Builder\Use_($name, Use_::TYPE_NORMAL); } /** * Creates a function use builder. * * @param Node\Name|string $name Name of the function to alias * * @return Builder\Use_ The created use function builder */ public function useFunction($name) : Builder\Use_ { return new Builder\Use_($name, Use_::TYPE_FUNCTION); } /** * Creates a constant use builder. * * @param Node\Name|string $name Name of the const to alias * * @return Builder\Use_ The created use const builder */ public function useConst($name) : Builder\Use_ { return new Builder\Use_($name, Use_::TYPE_CONSTANT); } /** * Creates a class constant builder. * * @param string|Identifier $name Name * @param Node\Expr|bool|null|int|float|string|array $value Value * * @return Builder\ClassConst The created use const builder */ public function classConst($name, $value) : Builder\ClassConst { return new Builder\ClassConst($name, $value); } /** * Creates an enum case builder. * * @param string|Identifier $name Name * * @return Builder\EnumCase The created use const builder */ public function enumCase($name) : Builder\EnumCase { return new Builder\EnumCase($name); } /** * Creates node a for a literal value. * * @param Expr|bool|null|int|float|string|array $value $value * * @return Expr */ public function val($value) : Expr { return BuilderHelpers::normalizeValue($value); } /** * Creates variable node. * * @param string|Expr $name Name * * @return Expr\Variable */ public function var($name) : Expr\Variable { if (!\is_string($name) && !$name instanceof Expr) { throw new \LogicException('Variable name must be string or Expr'); } return new Expr\Variable($name); } /** * Normalizes an argument list. * * Creates Arg nodes for all arguments and converts literal values to expressions. * * @param array $args List of arguments to normalize * * @return Arg[] */ public function args(array $args) : array { $normalizedArgs = []; foreach ($args as $key => $arg) { if (!($arg instanceof Arg)) { $arg = new Arg(BuilderHelpers::normalizeValue($arg)); } if (\is_string($key)) { $arg->name = BuilderHelpers::normalizeIdentifier($key); } $normalizedArgs[] = $arg; } return $normalizedArgs; } /** * Creates a function call node. * * @param string|Name|Expr $name Function name * @param array $args Function arguments * * @return Expr\FuncCall */ public function funcCall($name, array $args = []) : Expr\FuncCall { return new Expr\FuncCall( BuilderHelpers::normalizeNameOrExpr($name), $this->args($args) ); } /** * Creates a method call node. * * @param Expr $var Variable the method is called on * @param string|Identifier|Expr $name Method name * @param array $args Method arguments * * @return Expr\MethodCall */ public function methodCall(Expr $var, $name, array $args = []) : Expr\MethodCall { return new Expr\MethodCall( $var, BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args) ); } /** * Creates a static method call node. * * @param string|Name|Expr $class Class name * @param string|Identifier|Expr $name Method name * @param array $args Method arguments * * @return Expr\StaticCall */ public function staticCall($class, $name, array $args = []) : Expr\StaticCall { return new Expr\StaticCall( BuilderHelpers::normalizeNameOrExpr($class), BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args) ); } /** * Creates an object creation node. * * @param string|Name|Expr $class Class name * @param array $args Constructor arguments * * @return Expr\New_ */ public function new($class, array $args = []) : Expr\New_ { return new Expr\New_( BuilderHelpers::normalizeNameOrExpr($class), $this->args($args) ); } /** * Creates a constant fetch node. * * @param string|Name $name Constant name * * @return Expr\ConstFetch */ public function constFetch($name) : Expr\ConstFetch { return new Expr\ConstFetch(BuilderHelpers::normalizeName($name)); } /** * Creates a property fetch node. * * @param Expr $var Variable holding object * @param string|Identifier|Expr $name Property name * * @return Expr\PropertyFetch */ public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch { return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name)); } /** * Creates a class constant fetch node. * * @param string|Name|Expr $class Class name * @param string|Identifier $name Constant name * * @return Expr\ClassConstFetch */ public function classConstFetch($class, $name): Expr\ClassConstFetch { return new Expr\ClassConstFetch( BuilderHelpers::normalizeNameOrExpr($class), BuilderHelpers::normalizeIdentifier($name) ); } /** * Creates nested Concat nodes from a list of expressions. * * @param Expr|string ...$exprs Expressions or literal strings * * @return Concat */ public function concat(...$exprs) : Concat { $numExprs = count($exprs); if ($numExprs < 2) { throw new \LogicException('Expected at least two expressions'); } $lastConcat = $this->normalizeStringExpr($exprs[0]); for ($i = 1; $i < $numExprs; $i++) { $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i])); } return $lastConcat; } /** * @param string|Expr $expr * @return Expr */ private function normalizeStringExpr($expr) : Expr { if ($expr instanceof Expr) { return $expr; } if (\is_string($expr)) { return new String_($expr); } throw new \LogicException('Expected string or Expr'); } } php-parser/lib/PhpParser/Lexer/Emulative.php000064400000021541150250175720015031 0ustar00targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_2; unset($options['phpVersion']); parent::__construct($options); $emulators = [ new FlexibleDocStringEmulator(), new FnTokenEmulator(), new MatchTokenEmulator(), new CoaleseEqualTokenEmulator(), new NumericLiteralSeparatorEmulator(), new NullsafeTokenEmulator(), new AttributeEmulator(), new EnumTokenEmulator(), new ReadonlyTokenEmulator(), new ExplicitOctalEmulator(), new ReadonlyFunctionTokenEmulator(), ]; // Collect emulators that are relevant for the PHP version we're running // and the PHP version we're targeting for emulation. foreach ($emulators as $emulator) { $emulatorPhpVersion = $emulator->getPhpVersion(); if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) { $this->emulators[] = $emulator; } else if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) { $this->emulators[] = new ReverseEmulator($emulator); } } } public function startLexing(string $code, ErrorHandler $errorHandler = null) { $emulators = array_filter($this->emulators, function($emulator) use($code) { return $emulator->isEmulationNeeded($code); }); if (empty($emulators)) { // Nothing to emulate, yay parent::startLexing($code, $errorHandler); return; } $this->patches = []; foreach ($emulators as $emulator) { $code = $emulator->preprocessCode($code, $this->patches); } $collector = new ErrorHandler\Collecting(); parent::startLexing($code, $collector); $this->sortPatches(); $this->fixupTokens(); $errors = $collector->getErrors(); if (!empty($errors)) { $this->fixupErrors($errors); foreach ($errors as $error) { $errorHandler->handleError($error); } } foreach ($emulators as $emulator) { $this->tokens = $emulator->emulate($code, $this->tokens); } } private function isForwardEmulationNeeded(string $emulatorPhpVersion): bool { return version_compare(\PHP_VERSION, $emulatorPhpVersion, '<') && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>='); } private function isReverseEmulationNeeded(string $emulatorPhpVersion): bool { return version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=') && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<'); } private function sortPatches() { // Patches may be contributed by different emulators. // Make sure they are sorted by increasing patch position. usort($this->patches, function($p1, $p2) { return $p1[0] <=> $p2[0]; }); } private function fixupTokens() { if (\count($this->patches) === 0) { return; } // Load first patch $patchIdx = 0; list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; // We use a manual loop over the tokens, because we modify the array on the fly $pos = 0; for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) { $token = $this->tokens[$i]; if (\is_string($token)) { if ($patchPos === $pos) { // Only support replacement for string tokens. assert($patchType === 'replace'); $this->tokens[$i] = $patchText; // Fetch the next patch $patchIdx++; if ($patchIdx >= \count($this->patches)) { // No more patches, we're done return; } list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; } $pos += \strlen($token); continue; } $len = \strlen($token[1]); $posDelta = 0; while ($patchPos >= $pos && $patchPos < $pos + $len) { $patchTextLen = \strlen($patchText); if ($patchType === 'remove') { if ($patchPos === $pos && $patchTextLen === $len) { // Remove token entirely array_splice($this->tokens, $i, 1, []); $i--; $c--; } else { // Remove from token string $this->tokens[$i][1] = substr_replace( $token[1], '', $patchPos - $pos + $posDelta, $patchTextLen ); $posDelta -= $patchTextLen; } } elseif ($patchType === 'add') { // Insert into the token string $this->tokens[$i][1] = substr_replace( $token[1], $patchText, $patchPos - $pos + $posDelta, 0 ); $posDelta += $patchTextLen; } else if ($patchType === 'replace') { // Replace inside the token string $this->tokens[$i][1] = substr_replace( $token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen ); } else { assert(false); } // Fetch the next patch $patchIdx++; if ($patchIdx >= \count($this->patches)) { // No more patches, we're done return; } list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; // Multiple patches may apply to the same token. Reload the current one to check // If the new patch applies $token = $this->tokens[$i]; } $pos += $len; } // A patch did not apply assert(false); } /** * Fixup line and position information in errors. * * @param Error[] $errors */ private function fixupErrors(array $errors) { foreach ($errors as $error) { $attrs = $error->getAttributes(); $posDelta = 0; $lineDelta = 0; foreach ($this->patches as $patch) { list($patchPos, $patchType, $patchText) = $patch; if ($patchPos >= $attrs['startFilePos']) { // No longer relevant break; } if ($patchType === 'add') { $posDelta += strlen($patchText); $lineDelta += substr_count($patchText, "\n"); } else if ($patchType === 'remove') { $posDelta -= strlen($patchText); $lineDelta -= substr_count($patchText, "\n"); } } $attrs['startFilePos'] += $posDelta; $attrs['endFilePos'] += $posDelta; $attrs['startLine'] += $lineDelta; $attrs['endLine'] += $lineDelta; $error->setAttributes($attrs); } } } php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php000064400000000633150250175720020743 0ustar00getKeywordString()) !== false; } protected function isKeywordContext(array $tokens, int $pos): bool { $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos); return $previousNonSpaceToken === null || $previousNonSpaceToken[0] !== \T_OBJECT_OPERATOR; } public function emulate(string $code, array $tokens): array { $keywordString = $this->getKeywordString(); foreach ($tokens as $i => $token) { if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString && $this->isKeywordContext($tokens, $i)) { $tokens[$i][0] = $this->getKeywordToken(); } } return $tokens; } /** * @param mixed[] $tokens * @return array|string|null */ private function getPreviousNonSpaceToken(array $tokens, int $start) { for ($i = $start - 1; $i >= 0; --$i) { if ($tokens[$i][0] === T_WHITESPACE) { continue; } return $tokens[$i]; } return null; } public function reverseEmulate(string $code, array $tokens): array { $keywordToken = $this->getKeywordToken(); foreach ($tokens as $i => $token) { if ($token[0] === $keywordToken) { $tokens[$i][0] = \T_STRING; } } return $tokens; } } php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php000064400000002710150250175720022141 0ustar00resolveIntegerOrFloatToken($tokens[$i + 1][1]); array_splice($tokens, $i, 2, [ [$tokenKind, '0' . $tokens[$i + 1][1], $tokens[$i][2]], ]); $c--; } } return $tokens; } private function resolveIntegerOrFloatToken(string $str): int { $str = substr($str, 1); $str = str_replace('_', '', $str); $num = octdec($str); return is_float($num) ? \T_DNUMBER : \T_LNUMBER; } public function reverseEmulate(string $code, array $tokens): array { // Explicit octals were not legal code previously, don't bother. return $tokens; } }php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php000064400000001707150250175720021015 0ustar00emulator = $emulator; } public function getPhpVersion(): string { return $this->emulator->getPhpVersion(); } public function isEmulationNeeded(string $code): bool { return $this->emulator->isEmulationNeeded($code); } public function emulate(string $code, array $tokens): array { return $this->emulator->reverseEmulate($code, $tokens); } public function reverseEmulate(string $code, array $tokens): array { return $this->emulator->emulate($code, $tokens); } public function preprocessCode(string $code, array &$patches): string { return $code; } }php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php000064400000007106150250175720024201 0ustar00resolveIntegerOrFloatToken($match); $newTokens = [[$tokenKind, $match, $token[2]]]; $numTokens = 1; $len = $tokenLen; while ($matchLen > $len) { $nextToken = $tokens[$i + $numTokens]; $nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken; $nextTokenLen = \strlen($nextTokenText); $numTokens++; if ($matchLen < $len + $nextTokenLen) { // Split trailing characters into a partial token. assert(is_array($nextToken), "Partial token should be an array token"); $partialText = substr($nextTokenText, $matchLen - $len); $newTokens[] = [$nextToken[0], $partialText, $nextToken[2]]; break; } $len += $nextTokenLen; } array_splice($tokens, $i, $numTokens, $newTokens); $c -= $numTokens - \count($newTokens); $codeOffset += $matchLen; } return $tokens; } private function resolveIntegerOrFloatToken(string $str): int { $str = str_replace('_', '', $str); if (stripos($str, '0b') === 0) { $num = bindec($str); } elseif (stripos($str, '0x') === 0) { $num = hexdec($str); } elseif (stripos($str, '0') === 0 && ctype_digit($str)) { $num = octdec($str); } else { $num = +$str; } return is_float($num) ? T_DNUMBER : T_LNUMBER; } public function reverseEmulate(string $code, array $tokens): array { // Numeric separators were not legal code previously, don't bother. return $tokens; } } php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php000064400000001147150250175720020460 0ustar00') !== false; } public function emulate(string $code, array $tokens): array { // We need to manually iterate and manage a count because we'll change // the tokens array on the way $line = 1; for ($i = 0, $c = count($tokens); $i < $c; ++$i) { if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) { array_splice($tokens, $i, 2, [ [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line] ]); $c--; continue; } // Handle ?-> inside encapsed string. if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1]) && $tokens[$i - 1][0] === \T_VARIABLE && preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches) ) { $replacement = [ [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line], [\T_STRING, $matches[1], $line], ]; if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) { $replacement[] = [ \T_ENCAPSED_AND_WHITESPACE, \substr($tokens[$i][1], \strlen($matches[0])), $line ]; } array_splice($tokens, $i, 1, $replacement); $c += \count($replacement) - 1; continue; } if (\is_array($tokens[$i])) { $line += substr_count($tokens[$i][1], "\n"); } } return $tokens; } public function reverseEmulate(string $code, array $tokens): array { // ?-> was not valid code previously, don't bother. return $tokens; } } php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php000064400000001275150250175720021307 0ustar00\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?(?:;?[\r\n])?)/x REGEX; public function getPhpVersion(): string { return Emulative::PHP_7_3; } public function isEmulationNeeded(string $code) : bool { return strpos($code, '<<<') !== false; } public function emulate(string $code, array $tokens): array { // Handled by preprocessing + fixup. return $tokens; } public function reverseEmulate(string $code, array $tokens): array { // Not supported. return $tokens; } public function preprocessCode(string $code, array &$patches): string { if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) { // No heredoc/nowdoc found return $code; } // Keep track of how much we need to adjust string offsets due to the modifications we // already made $posDelta = 0; foreach ($matches as $match) { $indentation = $match['indentation'][0]; $indentationStart = $match['indentation'][1]; $separator = $match['separator'][0]; $separatorStart = $match['separator'][1]; if ($indentation === '' && $separator !== '') { // Ordinary heredoc/nowdoc continue; } if ($indentation !== '') { // Remove indentation $indentationLen = strlen($indentation); $code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen); $patches[] = [$indentationStart + $posDelta, 'add', $indentation]; $posDelta -= $indentationLen; } if ($separator === '') { // Insert newline as separator $code = substr_replace($code, "\n", $separatorStart + $posDelta, 0); $patches[] = [$separatorStart + $posDelta, 'remove', "\n"]; $posDelta += 1; } } return $code; } } php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php000064400000000645150250175720021437 0ustar00 [ 0, 1], Expr\BitwiseNot::class => [ 10, 1], Expr\PreInc::class => [ 10, 1], Expr\PreDec::class => [ 10, 1], Expr\PostInc::class => [ 10, -1], Expr\PostDec::class => [ 10, -1], Expr\UnaryPlus::class => [ 10, 1], Expr\UnaryMinus::class => [ 10, 1], Cast\Int_::class => [ 10, 1], Cast\Double::class => [ 10, 1], Cast\String_::class => [ 10, 1], Cast\Array_::class => [ 10, 1], Cast\Object_::class => [ 10, 1], Cast\Bool_::class => [ 10, 1], Cast\Unset_::class => [ 10, 1], Expr\ErrorSuppress::class => [ 10, 1], Expr\Instanceof_::class => [ 20, 0], Expr\BooleanNot::class => [ 30, 1], BinaryOp\Mul::class => [ 40, -1], BinaryOp\Div::class => [ 40, -1], BinaryOp\Mod::class => [ 40, -1], BinaryOp\Plus::class => [ 50, -1], BinaryOp\Minus::class => [ 50, -1], BinaryOp\Concat::class => [ 50, -1], BinaryOp\ShiftLeft::class => [ 60, -1], BinaryOp\ShiftRight::class => [ 60, -1], BinaryOp\Smaller::class => [ 70, 0], BinaryOp\SmallerOrEqual::class => [ 70, 0], BinaryOp\Greater::class => [ 70, 0], BinaryOp\GreaterOrEqual::class => [ 70, 0], BinaryOp\Equal::class => [ 80, 0], BinaryOp\NotEqual::class => [ 80, 0], BinaryOp\Identical::class => [ 80, 0], BinaryOp\NotIdentical::class => [ 80, 0], BinaryOp\Spaceship::class => [ 80, 0], BinaryOp\BitwiseAnd::class => [ 90, -1], BinaryOp\BitwiseXor::class => [100, -1], BinaryOp\BitwiseOr::class => [110, -1], BinaryOp\BooleanAnd::class => [120, -1], BinaryOp\BooleanOr::class => [130, -1], BinaryOp\Coalesce::class => [140, 1], Expr\Ternary::class => [150, 0], // parser uses %left for assignments, but they really behave as %right Expr\Assign::class => [160, 1], Expr\AssignRef::class => [160, 1], AssignOp\Plus::class => [160, 1], AssignOp\Minus::class => [160, 1], AssignOp\Mul::class => [160, 1], AssignOp\Div::class => [160, 1], AssignOp\Concat::class => [160, 1], AssignOp\Mod::class => [160, 1], AssignOp\BitwiseAnd::class => [160, 1], AssignOp\BitwiseOr::class => [160, 1], AssignOp\BitwiseXor::class => [160, 1], AssignOp\ShiftLeft::class => [160, 1], AssignOp\ShiftRight::class => [160, 1], AssignOp\Pow::class => [160, 1], AssignOp\Coalesce::class => [160, 1], Expr\YieldFrom::class => [165, 1], Expr\Print_::class => [168, 1], BinaryOp\LogicalAnd::class => [170, -1], BinaryOp\LogicalXor::class => [180, -1], BinaryOp\LogicalOr::class => [190, -1], Expr\Include_::class => [200, -1], ]; /** @var int Current indentation level. */ protected $indentLevel; /** @var string Newline including current indentation. */ protected $nl; /** @var string Token placed at end of doc string to ensure it is followed by a newline. */ protected $docStringEndToken; /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */ protected $canUseSemicolonNamespaces; /** @var array Pretty printer options */ protected $options; /** @var TokenStream Original tokens for use in format-preserving pretty print */ protected $origTokens; /** @var Internal\Differ Differ for node lists */ protected $nodeListDiffer; /** @var bool[] Map determining whether a certain character is a label character */ protected $labelCharMap; /** * @var int[][] Map from token classes and subnode names to FIXUP_* constants. This is used * during format-preserving prints to place additional parens/braces if necessary. */ protected $fixupMap; /** * @var int[][] Map from "{$node->getType()}->{$subNode}" to ['left' => $l, 'right' => $r], * where $l and $r specify the token type that needs to be stripped when removing * this node. */ protected $removalMap; /** * @var mixed[] Map from "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight]. * $find is an optional token after which the insertion occurs. $extraLeft/Right * are optionally added before/after the main insertions. */ protected $insertionMap; /** * @var string[] Map From "{$node->getType()}->{$subNode}" to string that should be inserted * between elements of this list subnode. */ protected $listInsertionMap; protected $emptyListInsertionMap; /** @var int[] Map from "{$node->getType()}->{$subNode}" to token before which the modifiers * should be reprinted. */ protected $modifierChangeMap; /** * Creates a pretty printer instance using the given options. * * Supported options: * * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array * syntax, if the node does not specify a format. * * @param array $options Dictionary of formatting options */ public function __construct(array $options = []) { $this->docStringEndToken = '_DOC_STRING_END_' . mt_rand(); $defaultOptions = ['shortArraySyntax' => false]; $this->options = $options + $defaultOptions; } /** * Reset pretty printing state. */ protected function resetState() { $this->indentLevel = 0; $this->nl = "\n"; $this->origTokens = null; } /** * Set indentation level * * @param int $level Level in number of spaces */ protected function setIndentLevel(int $level) { $this->indentLevel = $level; $this->nl = "\n" . \str_repeat(' ', $level); } /** * Increase indentation level. */ protected function indent() { $this->indentLevel += 4; $this->nl .= ' '; } /** * Decrease indentation level. */ protected function outdent() { assert($this->indentLevel >= 4); $this->indentLevel -= 4; $this->nl = "\n" . str_repeat(' ', $this->indentLevel); } /** * Pretty prints an array of statements. * * @param Node[] $stmts Array of statements * * @return string Pretty printed statements */ public function prettyPrint(array $stmts) : string { $this->resetState(); $this->preprocessNodes($stmts); return ltrim($this->handleMagicTokens($this->pStmts($stmts, false))); } /** * Pretty prints an expression. * * @param Expr $node Expression node * * @return string Pretty printed node */ public function prettyPrintExpr(Expr $node) : string { $this->resetState(); return $this->handleMagicTokens($this->p($node)); } /** * Pretty prints a file of statements (includes the opening prettyPrint($stmts); if ($stmts[0] instanceof Stmt\InlineHTML) { $p = preg_replace('/^<\?php\s+\?>\n?/', '', $p); } if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) { $p = preg_replace('/<\?php$/', '', rtrim($p)); } return $p; } /** * Preprocesses the top-level nodes to initialize pretty printer state. * * @param Node[] $nodes Array of nodes */ protected function preprocessNodes(array $nodes) { /* We can use semicolon-namespaces unless there is a global namespace declaration */ $this->canUseSemicolonNamespaces = true; foreach ($nodes as $node) { if ($node instanceof Stmt\Namespace_ && null === $node->name) { $this->canUseSemicolonNamespaces = false; break; } } } /** * Handles (and removes) no-indent and doc-string-end tokens. * * @param string $str * @return string */ protected function handleMagicTokens(string $str) : string { // Replace doc-string-end tokens with nothing or a newline $str = str_replace($this->docStringEndToken . ";\n", ";\n", $str); $str = str_replace($this->docStringEndToken, "\n", $str); return $str; } /** * Pretty prints an array of nodes (statements) and indents them optionally. * * @param Node[] $nodes Array of nodes * @param bool $indent Whether to indent the printed nodes * * @return string Pretty printed statements */ protected function pStmts(array $nodes, bool $indent = true) : string { if ($indent) { $this->indent(); } $result = ''; foreach ($nodes as $node) { $comments = $node->getComments(); if ($comments) { $result .= $this->nl . $this->pComments($comments); if ($node instanceof Stmt\Nop) { continue; } } $result .= $this->nl . $this->p($node); } if ($indent) { $this->outdent(); } return $result; } /** * Pretty-print an infix operation while taking precedence into account. * * @param string $class Node class of operator * @param Node $leftNode Left-hand side node * @param string $operatorString String representation of the operator * @param Node $rightNode Right-hand side node * * @return string Pretty printed infix operation */ protected function pInfixOp(string $class, Node $leftNode, string $operatorString, Node $rightNode) : string { list($precedence, $associativity) = $this->precedenceMap[$class]; return $this->pPrec($leftNode, $precedence, $associativity, -1) . $operatorString . $this->pPrec($rightNode, $precedence, $associativity, 1); } /** * Pretty-print a prefix operation while taking precedence into account. * * @param string $class Node class of operator * @param string $operatorString String representation of the operator * @param Node $node Node * * @return string Pretty printed prefix operation */ protected function pPrefixOp(string $class, string $operatorString, Node $node) : string { list($precedence, $associativity) = $this->precedenceMap[$class]; return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); } /** * Pretty-print a postfix operation while taking precedence into account. * * @param string $class Node class of operator * @param string $operatorString String representation of the operator * @param Node $node Node * * @return string Pretty printed postfix operation */ protected function pPostfixOp(string $class, Node $node, string $operatorString) : string { list($precedence, $associativity) = $this->precedenceMap[$class]; return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString; } /** * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. * * @param Node $node Node to pretty print * @param int $parentPrecedence Precedence of the parent operator * @param int $parentAssociativity Associativity of parent operator * (-1 is left, 0 is nonassoc, 1 is right) * @param int $childPosition Position of the node relative to the operator * (-1 is left, 1 is right) * * @return string The pretty printed node */ protected function pPrec(Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition) : string { $class = \get_class($node); if (isset($this->precedenceMap[$class])) { $childPrecedence = $this->precedenceMap[$class][0]; if ($childPrecedence > $parentPrecedence || ($parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition) ) { return '(' . $this->p($node) . ')'; } } return $this->p($node); } /** * Pretty prints an array of nodes and implodes the printed values. * * @param Node[] $nodes Array of Nodes to be printed * @param string $glue Character to implode with * * @return string Imploded pretty printed nodes */ protected function pImplode(array $nodes, string $glue = '') : string { $pNodes = []; foreach ($nodes as $node) { if (null === $node) { $pNodes[] = ''; } else { $pNodes[] = $this->p($node); } } return implode($glue, $pNodes); } /** * Pretty prints an array of nodes and implodes the printed values with commas. * * @param Node[] $nodes Array of Nodes to be printed * * @return string Comma separated pretty printed nodes */ protected function pCommaSeparated(array $nodes) : string { return $this->pImplode($nodes, ', '); } /** * Pretty prints a comma-separated list of nodes in multiline style, including comments. * * The result includes a leading newline and one level of indentation (same as pStmts). * * @param Node[] $nodes Array of Nodes to be printed * @param bool $trailingComma Whether to use a trailing comma * * @return string Comma separated pretty printed nodes in multiline style */ protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma) : string { $this->indent(); $result = ''; $lastIdx = count($nodes) - 1; foreach ($nodes as $idx => $node) { if ($node !== null) { $comments = $node->getComments(); if ($comments) { $result .= $this->nl . $this->pComments($comments); } $result .= $this->nl . $this->p($node); } else { $result .= $this->nl; } if ($trailingComma || $idx !== $lastIdx) { $result .= ','; } } $this->outdent(); return $result; } /** * Prints reformatted text of the passed comments. * * @param Comment[] $comments List of comments * * @return string Reformatted text of comments */ protected function pComments(array $comments) : string { $formattedComments = []; foreach ($comments as $comment) { $formattedComments[] = str_replace("\n", $this->nl, $comment->getReformattedText()); } return implode($this->nl, $formattedComments); } /** * Perform a format-preserving pretty print of an AST. * * The format preservation is best effort. For some changes to the AST the formatting will not * be preserved (at least not locally). * * In order to use this method a number of prerequisites must be satisfied: * * The startTokenPos and endTokenPos attributes in the lexer must be enabled. * * The CloningVisitor must be run on the AST prior to modification. * * The original tokens must be provided, using the getTokens() method on the lexer. * * @param Node[] $stmts Modified AST with links to original AST * @param Node[] $origStmts Original AST with token offset information * @param array $origTokens Tokens of the original code * * @return string */ public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string { $this->initializeNodeListDiffer(); $this->initializeLabelCharMap(); $this->initializeFixupMap(); $this->initializeRemovalMap(); $this->initializeInsertionMap(); $this->initializeListInsertionMap(); $this->initializeEmptyListInsertionMap(); $this->initializeModifierChangeMap(); $this->resetState(); $this->origTokens = new TokenStream($origTokens); $this->preprocessNodes($stmts); $pos = 0; $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null); if (null !== $result) { $result .= $this->origTokens->getTokenCode($pos, count($origTokens), 0); } else { // Fallback // TODO Add pStmts($stmts, false); } return ltrim($this->handleMagicTokens($result)); } protected function pFallback(Node $node) { return $this->{'p' . $node->getType()}($node); } /** * Pretty prints a node. * * This method also handles formatting preservation for nodes. * * @param Node $node Node to be pretty printed * @param bool $parentFormatPreserved Whether parent node has preserved formatting * * @return string Pretty printed node */ protected function p(Node $node, $parentFormatPreserved = false) : string { // No orig tokens means this is a normal pretty print without preservation of formatting if (!$this->origTokens) { return $this->{'p' . $node->getType()}($node); } /** @var Node $origNode */ $origNode = $node->getAttribute('origNode'); if (null === $origNode) { return $this->pFallback($node); } $class = \get_class($node); \assert($class === \get_class($origNode)); $startPos = $origNode->getStartTokenPos(); $endPos = $origNode->getEndTokenPos(); \assert($startPos >= 0 && $endPos >= 0); $fallbackNode = $node; if ($node instanceof Expr\New_ && $node->class instanceof Stmt\Class_) { // Normalize node structure of anonymous classes $node = PrintableNewAnonClassNode::fromNewNode($node); $origNode = PrintableNewAnonClassNode::fromNewNode($origNode); } // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting // is not preserved, then we need to use the fallback code to make sure the tags are // printed. if ($node instanceof Stmt\InlineHTML && !$parentFormatPreserved) { return $this->pFallback($fallbackNode); } $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos); $type = $node->getType(); $fixupInfo = $this->fixupMap[$class] ?? null; $result = ''; $pos = $startPos; foreach ($node->getSubNodeNames() as $subNodeName) { $subNode = $node->$subNodeName; $origSubNode = $origNode->$subNodeName; if ((!$subNode instanceof Node && $subNode !== null) || (!$origSubNode instanceof Node && $origSubNode !== null) ) { if ($subNode === $origSubNode) { // Unchanged, can reuse old code continue; } if (is_array($subNode) && is_array($origSubNode)) { // Array subnode changed, we might be able to reconstruct it $listResult = $this->pArray( $subNode, $origSubNode, $pos, $indentAdjustment, $type, $subNodeName, $fixupInfo[$subNodeName] ?? null ); if (null === $listResult) { return $this->pFallback($fallbackNode); } $result .= $listResult; continue; } if (is_int($subNode) && is_int($origSubNode)) { // Check if this is a modifier change $key = $type . '->' . $subNodeName; if (!isset($this->modifierChangeMap[$key])) { return $this->pFallback($fallbackNode); } $findToken = $this->modifierChangeMap[$key]; $result .= $this->pModifiers($subNode); $pos = $this->origTokens->findRight($pos, $findToken); continue; } // If a non-node, non-array subnode changed, we don't be able to do a partial // reconstructions, as we don't have enough offset information. Pretty print the // whole node instead. return $this->pFallback($fallbackNode); } $extraLeft = ''; $extraRight = ''; if ($origSubNode !== null) { $subStartPos = $origSubNode->getStartTokenPos(); $subEndPos = $origSubNode->getEndTokenPos(); \assert($subStartPos >= 0 && $subEndPos >= 0); } else { if ($subNode === null) { // Both null, nothing to do continue; } // A node has been inserted, check if we have insertion information for it $key = $type . '->' . $subNodeName; if (!isset($this->insertionMap[$key])) { return $this->pFallback($fallbackNode); } list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key]; if (null !== $findToken) { $subStartPos = $this->origTokens->findRight($pos, $findToken) + (int) !$beforeToken; } else { $subStartPos = $pos; } if (null === $extraLeft && null !== $extraRight) { // If inserting on the right only, skipping whitespace looks better $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos); } $subEndPos = $subStartPos - 1; } if (null === $subNode) { // A node has been removed, check if we have removal information for it $key = $type . '->' . $subNodeName; if (!isset($this->removalMap[$key])) { return $this->pFallback($fallbackNode); } // Adjust positions to account for additional tokens that must be skipped $removalInfo = $this->removalMap[$key]; if (isset($removalInfo['left'])) { $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1; } if (isset($removalInfo['right'])) { $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1; } } $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment); if (null !== $subNode) { $result .= $extraLeft; $origIndentLevel = $this->indentLevel; $this->setIndentLevel($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment); // If it's the same node that was previously in this position, it certainly doesn't // need fixup. It's important to check this here, because our fixup checks are more // conservative than strictly necessary. if (isset($fixupInfo[$subNodeName]) && $subNode->getAttribute('origNode') !== $origSubNode ) { $fixup = $fixupInfo[$subNodeName]; $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos); } else { $res = $this->p($subNode, true); } $this->safeAppend($result, $res); $this->setIndentLevel($origIndentLevel); $result .= $extraRight; } $pos = $subEndPos + 1; } $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment); return $result; } /** * Perform a format-preserving pretty print of an array. * * @param array $nodes New nodes * @param array $origNodes Original nodes * @param int $pos Current token position (updated by reference) * @param int $indentAdjustment Adjustment for indentation * @param string $parentNodeType Type of the containing node. * @param string $subNodeName Name of array subnode. * @param null|int $fixup Fixup information for array item nodes * * @return null|string Result of pretty print or null if cannot preserve formatting */ protected function pArray( array $nodes, array $origNodes, int &$pos, int $indentAdjustment, string $parentNodeType, string $subNodeName, $fixup ) { $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes); $mapKey = $parentNodeType . '->' . $subNodeName; $insertStr = $this->listInsertionMap[$mapKey] ?? null; $isStmtList = $subNodeName === 'stmts'; $beforeFirstKeepOrReplace = true; $skipRemovedNode = false; $delayedAdd = []; $lastElemIndentLevel = $this->indentLevel; $insertNewline = false; if ($insertStr === "\n") { $insertStr = ''; $insertNewline = true; } if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) { $startPos = $origNodes[0]->getStartTokenPos(); $endPos = $origNodes[0]->getEndTokenPos(); \assert($startPos >= 0 && $endPos >= 0); if (!$this->origTokens->haveBraces($startPos, $endPos)) { // This was a single statement without braces, but either additional statements // have been added, or the single statement has been removed. This requires the // addition of braces. For now fall back. // TODO: Try to preserve formatting return null; } } $result = ''; foreach ($diff as $i => $diffElem) { $diffType = $diffElem->type; /** @var Node|null $arrItem */ $arrItem = $diffElem->new; /** @var Node|null $origArrItem */ $origArrItem = $diffElem->old; if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) { $beforeFirstKeepOrReplace = false; if ($origArrItem === null || $arrItem === null) { // We can only handle the case where both are null if ($origArrItem === $arrItem) { continue; } return null; } if (!$arrItem instanceof Node || !$origArrItem instanceof Node) { // We can only deal with nodes. This can occur for Names, which use string arrays. return null; } $itemStartPos = $origArrItem->getStartTokenPos(); $itemEndPos = $origArrItem->getEndTokenPos(); \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos); $origIndentLevel = $this->indentLevel; $lastElemIndentLevel = $this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment; $this->setIndentLevel($lastElemIndentLevel); $comments = $arrItem->getComments(); $origComments = $origArrItem->getComments(); $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos; \assert($commentStartPos >= 0); if ($commentStartPos < $pos) { // Comments may be assigned to multiple nodes if they start at the same position. // Make sure we don't try to print them multiple times. $commentStartPos = $itemStartPos; } if ($skipRemovedNode) { if ($isStmtList && ($this->origTokens->haveBracesInRange($pos, $itemStartPos) || $this->origTokens->haveTagInRange($pos, $itemStartPos))) { // We'd remove the brace of a code block. // TODO: Preserve formatting. $this->setIndentLevel($origIndentLevel); return null; } } else { $result .= $this->origTokens->getTokenCode( $pos, $commentStartPos, $indentAdjustment); } if (!empty($delayedAdd)) { /** @var Node $delayedAddNode */ foreach ($delayedAdd as $delayedAddNode) { if ($insertNewline) { $delayedAddComments = $delayedAddNode->getComments(); if ($delayedAddComments) { $result .= $this->pComments($delayedAddComments) . $this->nl; } } $this->safeAppend($result, $this->p($delayedAddNode, true)); if ($insertNewline) { $result .= $insertStr . $this->nl; } else { $result .= $insertStr; } } $delayedAdd = []; } if ($comments !== $origComments) { if ($comments) { $result .= $this->pComments($comments) . $this->nl; } } else { $result .= $this->origTokens->getTokenCode( $commentStartPos, $itemStartPos, $indentAdjustment); } // If we had to remove anything, we have done so now. $skipRemovedNode = false; } elseif ($diffType === DiffElem::TYPE_ADD) { if (null === $insertStr) { // We don't have insertion information for this list type return null; } // We go multiline if the original code was multiline, // or if it's an array item with a comment above it. if ($insertStr === ', ' && ($this->isMultiline($origNodes) || $arrItem->getComments()) ) { $insertStr = ','; $insertNewline = true; } if ($beforeFirstKeepOrReplace) { // Will be inserted at the next "replace" or "keep" element $delayedAdd[] = $arrItem; continue; } $itemStartPos = $pos; $itemEndPos = $pos - 1; $origIndentLevel = $this->indentLevel; $this->setIndentLevel($lastElemIndentLevel); if ($insertNewline) { $result .= $insertStr . $this->nl; $comments = $arrItem->getComments(); if ($comments) { $result .= $this->pComments($comments) . $this->nl; } } else { $result .= $insertStr; } } elseif ($diffType === DiffElem::TYPE_REMOVE) { if (!$origArrItem instanceof Node) { // We only support removal for nodes return null; } $itemStartPos = $origArrItem->getStartTokenPos(); $itemEndPos = $origArrItem->getEndTokenPos(); \assert($itemStartPos >= 0 && $itemEndPos >= 0); // Consider comments part of the node. $origComments = $origArrItem->getComments(); if ($origComments) { $itemStartPos = $origComments[0]->getStartTokenPos(); } if ($i === 0) { // If we're removing from the start, keep the tokens before the node and drop those after it, // instead of the other way around. $result .= $this->origTokens->getTokenCode( $pos, $itemStartPos, $indentAdjustment); $skipRemovedNode = true; } else { if ($isStmtList && ($this->origTokens->haveBracesInRange($pos, $itemStartPos) || $this->origTokens->haveTagInRange($pos, $itemStartPos))) { // We'd remove the brace of a code block. // TODO: Preserve formatting. return null; } } $pos = $itemEndPos + 1; continue; } else { throw new \Exception("Shouldn't happen"); } if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) { $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos); } else { $res = $this->p($arrItem, true); } $this->safeAppend($result, $res); $this->setIndentLevel($origIndentLevel); $pos = $itemEndPos + 1; } if ($skipRemovedNode) { // TODO: Support removing single node. return null; } if (!empty($delayedAdd)) { if (!isset($this->emptyListInsertionMap[$mapKey])) { return null; } list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey]; if (null !== $findToken) { $insertPos = $this->origTokens->findRight($pos, $findToken) + 1; $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment); $pos = $insertPos; } $first = true; $result .= $extraLeft; foreach ($delayedAdd as $delayedAddNode) { if (!$first) { $result .= $insertStr; if ($insertNewline) { $result .= $this->nl; } } $result .= $this->p($delayedAddNode, true); $first = false; } $result .= $extraRight === "\n" ? $this->nl : $extraRight; } return $result; } /** * Print node with fixups. * * Fixups here refer to the addition of extra parentheses, braces or other characters, that * are required to preserve program semantics in a certain context (e.g. to maintain precedence * or because only certain expressions are allowed in certain places). * * @param int $fixup Fixup type * @param Node $subNode Subnode to print * @param string|null $parentClass Class of parent node * @param int $subStartPos Original start pos of subnode * @param int $subEndPos Original end pos of subnode * * @return string Result of fixed-up print of subnode */ protected function pFixup(int $fixup, Node $subNode, $parentClass, int $subStartPos, int $subEndPos) : string { switch ($fixup) { case self::FIXUP_PREC_LEFT: case self::FIXUP_PREC_RIGHT: if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { list($precedence, $associativity) = $this->precedenceMap[$parentClass]; return $this->pPrec($subNode, $precedence, $associativity, $fixup === self::FIXUP_PREC_LEFT ? -1 : 1); } break; case self::FIXUP_CALL_LHS: if ($this->callLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos) ) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_DEREF_LHS: if ($this->dereferenceLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos) ) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_BRACED_NAME: case self::FIXUP_VAR_BRACED_NAME: if ($subNode instanceof Expr && !$this->origTokens->haveBraces($subStartPos, $subEndPos) ) { return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '') . '{' . $this->p($subNode) . '}'; } break; case self::FIXUP_ENCAPSED: if (!$subNode instanceof Scalar\EncapsedStringPart && !$this->origTokens->haveBraces($subStartPos, $subEndPos) ) { return '{' . $this->p($subNode) . '}'; } break; default: throw new \Exception('Cannot happen'); } // Nothing special to do return $this->p($subNode); } /** * Appends to a string, ensuring whitespace between label characters. * * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x". * Without safeAppend the result would be "echox", which does not preserve semantics. * * @param string $str * @param string $append */ protected function safeAppend(string &$str, string $append) { if ($str === "") { $str = $append; return; } if ($append === "") { return; } if (!$this->labelCharMap[$append[0]] || !$this->labelCharMap[$str[\strlen($str) - 1]]) { $str .= $append; } else { $str .= " " . $append; } } /** * Determines whether the LHS of a call must be wrapped in parenthesis. * * @param Node $node LHS of a call * * @return bool Whether parentheses are required */ protected function callLhsRequiresParens(Node $node) : bool { return !($node instanceof Node\Name || $node instanceof Expr\Variable || $node instanceof Expr\ArrayDimFetch || $node instanceof Expr\FuncCall || $node instanceof Expr\MethodCall || $node instanceof Expr\NullsafeMethodCall || $node instanceof Expr\StaticCall || $node instanceof Expr\Array_); } /** * Determines whether the LHS of a dereferencing operation must be wrapped in parenthesis. * * @param Node $node LHS of dereferencing operation * * @return bool Whether parentheses are required */ protected function dereferenceLhsRequiresParens(Node $node) : bool { return !($node instanceof Expr\Variable || $node instanceof Node\Name || $node instanceof Expr\ArrayDimFetch || $node instanceof Expr\PropertyFetch || $node instanceof Expr\NullsafePropertyFetch || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\FuncCall || $node instanceof Expr\MethodCall || $node instanceof Expr\NullsafeMethodCall || $node instanceof Expr\StaticCall || $node instanceof Expr\Array_ || $node instanceof Scalar\String_ || $node instanceof Expr\ConstFetch || $node instanceof Expr\ClassConstFetch); } /** * Print modifiers, including trailing whitespace. * * @param int $modifiers Modifier mask to print * * @return string Printed modifiers */ protected function pModifiers(int $modifiers) { return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : '') . ($modifiers & Stmt\Class_::MODIFIER_READONLY ? 'readonly ' : ''); } /** * Determine whether a list of nodes uses multiline formatting. * * @param (Node|null)[] $nodes Node list * * @return bool Whether multiline formatting is used */ protected function isMultiline(array $nodes) : bool { if (\count($nodes) < 2) { return false; } $pos = -1; foreach ($nodes as $node) { if (null === $node) { continue; } $endPos = $node->getEndTokenPos() + 1; if ($pos >= 0) { $text = $this->origTokens->getTokenCode($pos, $endPos, 0); if (false === strpos($text, "\n")) { // We require that a newline is present between *every* item. If the formatting // is inconsistent, with only some items having newlines, we don't consider it // as multiline return false; } } $pos = $endPos; } return true; } /** * Lazily initializes label char map. * * The label char map determines whether a certain character may occur in a label. */ protected function initializeLabelCharMap() { if ($this->labelCharMap) return; $this->labelCharMap = []; for ($i = 0; $i < 256; $i++) { // Since PHP 7.1 The lower range is 0x80. However, we also want to support code for // older versions. $chr = chr($i); $this->labelCharMap[$chr] = $i >= 0x7f || ctype_alnum($chr); } } /** * Lazily initializes node list differ. * * The node list differ is used to determine differences between two array subnodes. */ protected function initializeNodeListDiffer() { if ($this->nodeListDiffer) return; $this->nodeListDiffer = new Internal\Differ(function ($a, $b) { if ($a instanceof Node && $b instanceof Node) { return $a === $b->getAttribute('origNode'); } // Can happen for array destructuring return $a === null && $b === null; }); } /** * Lazily initializes fixup map. * * The fixup map is used to determine whether a certain subnode of a certain node may require * some kind of "fixup" operation, e.g. the addition of parenthesis or braces. */ protected function initializeFixupMap() { if ($this->fixupMap) return; $this->fixupMap = [ Expr\PreInc::class => ['var' => self::FIXUP_PREC_RIGHT], Expr\PreDec::class => ['var' => self::FIXUP_PREC_RIGHT], Expr\PostInc::class => ['var' => self::FIXUP_PREC_LEFT], Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT], Expr\Instanceof_::class => [ 'expr' => self::FIXUP_PREC_LEFT, 'class' => self::FIXUP_PREC_RIGHT, // TODO: FIXUP_NEW_VARIABLE ], Expr\Ternary::class => [ 'cond' => self::FIXUP_PREC_LEFT, 'else' => self::FIXUP_PREC_RIGHT, ], Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS], Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS], Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS], Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS], Expr\New_::class => ['class' => self::FIXUP_DEREF_LHS], // TODO: FIXUP_NEW_VARIABLE Expr\MethodCall::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Expr\NullsafeMethodCall::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Expr\StaticPropertyFetch::class => [ 'class' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_VAR_BRACED_NAME, ], Expr\PropertyFetch::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Expr\NullsafePropertyFetch::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Scalar\Encapsed::class => [ 'parts' => self::FIXUP_ENCAPSED, ], ]; $binaryOps = [ BinaryOp\Pow::class, BinaryOp\Mul::class, BinaryOp\Div::class, BinaryOp\Mod::class, BinaryOp\Plus::class, BinaryOp\Minus::class, BinaryOp\Concat::class, BinaryOp\ShiftLeft::class, BinaryOp\ShiftRight::class, BinaryOp\Smaller::class, BinaryOp\SmallerOrEqual::class, BinaryOp\Greater::class, BinaryOp\GreaterOrEqual::class, BinaryOp\Equal::class, BinaryOp\NotEqual::class, BinaryOp\Identical::class, BinaryOp\NotIdentical::class, BinaryOp\Spaceship::class, BinaryOp\BitwiseAnd::class, BinaryOp\BitwiseXor::class, BinaryOp\BitwiseOr::class, BinaryOp\BooleanAnd::class, BinaryOp\BooleanOr::class, BinaryOp\Coalesce::class, BinaryOp\LogicalAnd::class, BinaryOp\LogicalXor::class, BinaryOp\LogicalOr::class, ]; foreach ($binaryOps as $binaryOp) { $this->fixupMap[$binaryOp] = [ 'left' => self::FIXUP_PREC_LEFT, 'right' => self::FIXUP_PREC_RIGHT ]; } $assignOps = [ Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class, AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class, AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class, AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class ]; foreach ($assignOps as $assignOp) { $this->fixupMap[$assignOp] = [ 'var' => self::FIXUP_PREC_LEFT, 'expr' => self::FIXUP_PREC_RIGHT, ]; } $prefixOps = [ Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class, Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class, Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class, Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class, ]; foreach ($prefixOps as $prefixOp) { $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT]; } } /** * Lazily initializes the removal map. * * The removal map is used to determine which additional tokens should be removed when a * certain node is replaced by null. */ protected function initializeRemovalMap() { if ($this->removalMap) return; $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE]; $stripLeft = ['left' => \T_WHITESPACE]; $stripRight = ['right' => \T_WHITESPACE]; $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW]; $stripColon = ['left' => ':']; $stripEquals = ['left' => '=']; $this->removalMap = [ 'Expr_ArrayDimFetch->dim' => $stripBoth, 'Expr_ArrayItem->key' => $stripDoubleArrow, 'Expr_ArrowFunction->returnType' => $stripColon, 'Expr_Closure->returnType' => $stripColon, 'Expr_Exit->expr' => $stripBoth, 'Expr_Ternary->if' => $stripBoth, 'Expr_Yield->key' => $stripDoubleArrow, 'Expr_Yield->value' => $stripBoth, 'Param->type' => $stripRight, 'Param->default' => $stripEquals, 'Stmt_Break->num' => $stripBoth, 'Stmt_Catch->var' => $stripLeft, 'Stmt_ClassMethod->returnType' => $stripColon, 'Stmt_Class->extends' => ['left' => \T_EXTENDS], 'Stmt_Enum->scalarType' => $stripColon, 'Stmt_EnumCase->expr' => $stripEquals, 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], 'Stmt_Continue->num' => $stripBoth, 'Stmt_Foreach->keyVar' => $stripDoubleArrow, 'Stmt_Function->returnType' => $stripColon, 'Stmt_If->else' => $stripLeft, 'Stmt_Namespace->name' => $stripLeft, 'Stmt_Property->type' => $stripRight, 'Stmt_PropertyProperty->default' => $stripEquals, 'Stmt_Return->expr' => $stripBoth, 'Stmt_StaticVar->default' => $stripEquals, 'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft, 'Stmt_TryCatch->finally' => $stripLeft, // 'Stmt_Case->cond': Replace with "default" // 'Stmt_Class->name': Unclear what to do // 'Stmt_Declare->stmts': Not a plain node // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a plain node ]; } protected function initializeInsertionMap() { if ($this->insertionMap) return; // TODO: "yield" where both key and value are inserted doesn't work // [$find, $beforeToken, $extraLeft, $extraRight] $this->insertionMap = [ 'Expr_ArrayDimFetch->dim' => ['[', false, null, null], 'Expr_ArrayItem->key' => [null, false, null, ' => '], 'Expr_ArrowFunction->returnType' => [')', false, ' : ', null], 'Expr_Closure->returnType' => [')', false, ' : ', null], 'Expr_Ternary->if' => ['?', false, ' ', ' '], 'Expr_Yield->key' => [\T_YIELD, false, null, ' => '], 'Expr_Yield->value' => [\T_YIELD, false, ' ', null], 'Param->type' => [null, false, null, ' '], 'Param->default' => [null, false, ' = ', null], 'Stmt_Break->num' => [\T_BREAK, false, ' ', null], 'Stmt_Catch->var' => [null, false, ' ', null], 'Stmt_ClassMethod->returnType' => [')', false, ' : ', null], 'Stmt_Class->extends' => [null, false, ' extends ', null], 'Stmt_Enum->scalarType' => [null, false, ' : ', null], 'Stmt_EnumCase->expr' => [null, false, ' = ', null], 'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null], 'Stmt_Continue->num' => [\T_CONTINUE, false, ' ', null], 'Stmt_Foreach->keyVar' => [\T_AS, false, null, ' => '], 'Stmt_Function->returnType' => [')', false, ' : ', null], 'Stmt_If->else' => [null, false, ' ', null], 'Stmt_Namespace->name' => [\T_NAMESPACE, false, ' ', null], 'Stmt_Property->type' => [\T_VARIABLE, true, null, ' '], 'Stmt_PropertyProperty->default' => [null, false, ' = ', null], 'Stmt_Return->expr' => [\T_RETURN, false, ' ', null], 'Stmt_StaticVar->default' => [null, false, ' = ', null], //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO 'Stmt_TryCatch->finally' => [null, false, ' ', null], // 'Expr_Exit->expr': Complicated due to optional () // 'Stmt_Case->cond': Conversion from default to case // 'Stmt_Class->name': Unclear // 'Stmt_Declare->stmts': Not a proper node // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a proper node ]; } protected function initializeListInsertionMap() { if ($this->listInsertionMap) return; $this->listInsertionMap = [ // special //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully //'Scalar_Encapsed->parts' => '', 'Stmt_Catch->types' => '|', 'UnionType->types' => '|', 'IntersectionType->types' => '&', 'Stmt_If->elseifs' => ' ', 'Stmt_TryCatch->catches' => ' ', // comma-separated lists 'Expr_Array->items' => ', ', 'Expr_ArrowFunction->params' => ', ', 'Expr_Closure->params' => ', ', 'Expr_Closure->uses' => ', ', 'Expr_FuncCall->args' => ', ', 'Expr_Isset->vars' => ', ', 'Expr_List->items' => ', ', 'Expr_MethodCall->args' => ', ', 'Expr_NullsafeMethodCall->args' => ', ', 'Expr_New->args' => ', ', 'Expr_PrintableNewAnonClass->args' => ', ', 'Expr_StaticCall->args' => ', ', 'Stmt_ClassConst->consts' => ', ', 'Stmt_ClassMethod->params' => ', ', 'Stmt_Class->implements' => ', ', 'Stmt_Enum->implements' => ', ', 'Expr_PrintableNewAnonClass->implements' => ', ', 'Stmt_Const->consts' => ', ', 'Stmt_Declare->declares' => ', ', 'Stmt_Echo->exprs' => ', ', 'Stmt_For->init' => ', ', 'Stmt_For->cond' => ', ', 'Stmt_For->loop' => ', ', 'Stmt_Function->params' => ', ', 'Stmt_Global->vars' => ', ', 'Stmt_GroupUse->uses' => ', ', 'Stmt_Interface->extends' => ', ', 'Stmt_Match->arms' => ', ', 'Stmt_Property->props' => ', ', 'Stmt_StaticVar->vars' => ', ', 'Stmt_TraitUse->traits' => ', ', 'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ', 'Stmt_Unset->vars' => ', ', 'Stmt_Use->uses' => ', ', 'MatchArm->conds' => ', ', 'AttributeGroup->attrs' => ', ', // statement lists 'Expr_Closure->stmts' => "\n", 'Stmt_Case->stmts' => "\n", 'Stmt_Catch->stmts' => "\n", 'Stmt_Class->stmts' => "\n", 'Stmt_Enum->stmts' => "\n", 'Expr_PrintableNewAnonClass->stmts' => "\n", 'Stmt_Interface->stmts' => "\n", 'Stmt_Trait->stmts' => "\n", 'Stmt_ClassMethod->stmts' => "\n", 'Stmt_Declare->stmts' => "\n", 'Stmt_Do->stmts' => "\n", 'Stmt_ElseIf->stmts' => "\n", 'Stmt_Else->stmts' => "\n", 'Stmt_Finally->stmts' => "\n", 'Stmt_Foreach->stmts' => "\n", 'Stmt_For->stmts' => "\n", 'Stmt_Function->stmts' => "\n", 'Stmt_If->stmts' => "\n", 'Stmt_Namespace->stmts' => "\n", 'Stmt_Class->attrGroups' => "\n", 'Stmt_Enum->attrGroups' => "\n", 'Stmt_EnumCase->attrGroups' => "\n", 'Stmt_Interface->attrGroups' => "\n", 'Stmt_Trait->attrGroups' => "\n", 'Stmt_Function->attrGroups' => "\n", 'Stmt_ClassMethod->attrGroups' => "\n", 'Stmt_ClassConst->attrGroups' => "\n", 'Stmt_Property->attrGroups' => "\n", 'Expr_PrintableNewAnonClass->attrGroups' => ' ', 'Expr_Closure->attrGroups' => ' ', 'Expr_ArrowFunction->attrGroups' => ' ', 'Param->attrGroups' => ' ', 'Stmt_Switch->cases' => "\n", 'Stmt_TraitUse->adaptations' => "\n", 'Stmt_TryCatch->stmts' => "\n", 'Stmt_While->stmts' => "\n", // dummy for top-level context 'File->stmts' => "\n", ]; } protected function initializeEmptyListInsertionMap() { if ($this->emptyListInsertionMap) return; // TODO Insertion into empty statement lists. // [$find, $extraLeft, $extraRight] $this->emptyListInsertionMap = [ 'Expr_ArrowFunction->params' => ['(', '', ''], 'Expr_Closure->uses' => [')', ' use(', ')'], 'Expr_Closure->params' => ['(', '', ''], 'Expr_FuncCall->args' => ['(', '', ''], 'Expr_MethodCall->args' => ['(', '', ''], 'Expr_NullsafeMethodCall->args' => ['(', '', ''], 'Expr_New->args' => ['(', '', ''], 'Expr_PrintableNewAnonClass->args' => ['(', '', ''], 'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''], 'Expr_StaticCall->args' => ['(', '', ''], 'Stmt_Class->implements' => [null, ' implements ', ''], 'Stmt_Enum->implements' => [null, ' implements ', ''], 'Stmt_ClassMethod->params' => ['(', '', ''], 'Stmt_Interface->extends' => [null, ' extends ', ''], 'Stmt_Function->params' => ['(', '', ''], 'Stmt_Interface->attrGroups' => [null, '', "\n"], 'Stmt_Class->attrGroups' => [null, '', "\n"], 'Stmt_ClassConst->attrGroups' => [null, '', "\n"], 'Stmt_ClassMethod->attrGroups' => [null, '', "\n"], 'Stmt_Function->attrGroups' => [null, '', "\n"], 'Stmt_Property->attrGroups' => [null, '', "\n"], 'Stmt_Trait->attrGroups' => [null, '', "\n"], 'Expr_ArrowFunction->attrGroups' => [null, '', ' '], 'Expr_Closure->attrGroups' => [null, '', ' '], 'Expr_PrintableNewAnonClass->attrGroups' => [\T_NEW, ' ', ''], /* These cannot be empty to start with: * Expr_Isset->vars * Stmt_Catch->types * Stmt_Const->consts * Stmt_ClassConst->consts * Stmt_Declare->declares * Stmt_Echo->exprs * Stmt_Global->vars * Stmt_GroupUse->uses * Stmt_Property->props * Stmt_StaticVar->vars * Stmt_TraitUse->traits * Stmt_TraitUseAdaptation_Precedence->insteadof * Stmt_Unset->vars * Stmt_Use->uses * UnionType->types */ /* TODO * Stmt_If->elseifs * Stmt_TryCatch->catches * Expr_Array->items * Expr_List->items * Stmt_For->init * Stmt_For->cond * Stmt_For->loop */ ]; } protected function initializeModifierChangeMap() { if ($this->modifierChangeMap) return; $this->modifierChangeMap = [ 'Stmt_ClassConst->flags' => \T_CONST, 'Stmt_ClassMethod->flags' => \T_FUNCTION, 'Stmt_Class->flags' => \T_CLASS, 'Stmt_Property->flags' => \T_VARIABLE, 'Param->flags' => \T_VARIABLE, //'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO ]; // List of integer subnodes that are not modifiers: // Expr_Include->type // Stmt_GroupUse->type // Stmt_Use->type // Stmt_UseUse->type } } php-parser/lib/PhpParser/Lexer.php000064400000057017150250175720013105 0ustar00defineCompatibilityTokens(); $this->tokenMap = $this->createTokenMap(); $this->identifierTokens = $this->createIdentifierTokenMap(); // map of tokens to drop while lexing (the map is only used for isset lookup, // that's why the value is simply set to 1; the value is never actually used.) $this->dropTokens = array_fill_keys( [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1 ); $defaultAttributes = ['comments', 'startLine', 'endLine']; $usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true); // Create individual boolean properties to make these checks faster. $this->attributeStartLineUsed = isset($usedAttributes['startLine']); $this->attributeEndLineUsed = isset($usedAttributes['endLine']); $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']); $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']); $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']); $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']); $this->attributeCommentsUsed = isset($usedAttributes['comments']); } /** * Initializes the lexer for lexing the provided source code. * * This function does not throw if lexing errors occur. Instead, errors may be retrieved using * the getErrors() method. * * @param string $code The source code to lex * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to * ErrorHandler\Throwing */ public function startLexing(string $code, ErrorHandler $errorHandler = null) { if (null === $errorHandler) { $errorHandler = new ErrorHandler\Throwing(); } $this->code = $code; // keep the code around for __halt_compiler() handling $this->pos = -1; $this->line = 1; $this->filePos = 0; // If inline HTML occurs without preceding code, treat it as if it had a leading newline. // This ensures proper composability, because having a newline is the "safe" assumption. $this->prevCloseTagHasNewline = true; $scream = ini_set('xdebug.scream', '0'); $this->tokens = @token_get_all($code); $this->postprocessTokens($errorHandler); if (false !== $scream) { ini_set('xdebug.scream', $scream); } } private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) { $tokens = []; for ($i = $start; $i < $end; $i++) { $chr = $this->code[$i]; if ($chr === "\0") { // PHP cuts error message after null byte, so need special case $errorMsg = 'Unexpected null byte'; } else { $errorMsg = sprintf( 'Unexpected character "%s" (ASCII %d)', $chr, ord($chr) ); } $tokens[] = [\T_BAD_CHARACTER, $chr, $line]; $errorHandler->handleError(new Error($errorMsg, [ 'startLine' => $line, 'endLine' => $line, 'startFilePos' => $i, 'endFilePos' => $i, ])); } return $tokens; } /** * Check whether comment token is unterminated. * * @return bool */ private function isUnterminatedComment($token) : bool { return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT) && substr($token[1], 0, 2) === '/*' && substr($token[1], -2) !== '*/'; } protected function postprocessTokens(ErrorHandler $errorHandler) { // PHP's error handling for token_get_all() is rather bad, so if we want detailed // error information we need to compute it ourselves. Invalid character errors are // detected by finding "gaps" in the token array. Unterminated comments are detected // by checking if a trailing comment has a "*/" at the end. // // Additionally, we perform a number of canonicalizations here: // * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore. // * Use PHP 8.0 T_NAME_* tokens. // * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and // T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types. $filePos = 0; $line = 1; $numTokens = \count($this->tokens); for ($i = 0; $i < $numTokens; $i++) { $token = $this->tokens[$i]; // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token. // In this case we only need to emit an error. if ($token[0] === \T_BAD_CHARACTER) { $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler); } if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*' && preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) { $trailingNewline = $matches[0]; $token[1] = substr($token[1], 0, -strlen($trailingNewline)); $this->tokens[$i] = $token; if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) { // Move trailing newline into following T_WHITESPACE token, if it already exists. $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1]; $this->tokens[$i + 1][2]--; } else { // Otherwise, we need to create a new T_WHITESPACE token. array_splice($this->tokens, $i + 1, 0, [ [\T_WHITESPACE, $trailingNewline, $line], ]); $numTokens++; } } // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING // into a single token. if (\is_array($token) && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) { $lastWasSeparator = $token[0] === \T_NS_SEPARATOR; $text = $token[1]; for ($j = $i + 1; isset($this->tokens[$j]); $j++) { if ($lastWasSeparator) { if (!isset($this->identifierTokens[$this->tokens[$j][0]])) { break; } $lastWasSeparator = false; } else { if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) { break; } $lastWasSeparator = true; } $text .= $this->tokens[$j][1]; } if ($lastWasSeparator) { // Trailing separator is not part of the name. $j--; $text = substr($text, 0, -1); } if ($j > $i + 1) { if ($token[0] === \T_NS_SEPARATOR) { $type = \T_NAME_FULLY_QUALIFIED; } else if ($token[0] === \T_NAMESPACE) { $type = \T_NAME_RELATIVE; } else { $type = \T_NAME_QUALIFIED; } $token = [$type, $text, $line]; array_splice($this->tokens, $i, $j - $i, [$token]); $numTokens -= $j - $i - 1; } } if ($token === '&') { $next = $i + 1; while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) { $next++; } $followedByVarOrVarArg = isset($this->tokens[$next]) && ($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS); $this->tokens[$i] = $token = [ $followedByVarOrVarArg ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, '&', $line, ]; } $tokenValue = \is_string($token) ? $token : $token[1]; $tokenLen = \strlen($tokenValue); if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) { // Something is missing, must be an invalid character $nextFilePos = strpos($this->code, $tokenValue, $filePos); $badCharTokens = $this->handleInvalidCharacterRange( $filePos, $nextFilePos, $line, $errorHandler); $filePos = (int) $nextFilePos; array_splice($this->tokens, $i, 0, $badCharTokens); $numTokens += \count($badCharTokens); $i += \count($badCharTokens); } $filePos += $tokenLen; $line += substr_count($tokenValue, "\n"); } if ($filePos !== \strlen($this->code)) { if (substr($this->code, $filePos, 2) === '/*') { // Unlike PHP, HHVM will drop unterminated comments entirely $comment = substr($this->code, $filePos); $errorHandler->handleError(new Error('Unterminated comment', [ 'startLine' => $line, 'endLine' => $line + substr_count($comment, "\n"), 'startFilePos' => $filePos, 'endFilePos' => $filePos + \strlen($comment), ])); // Emulate the PHP behavior $isDocComment = isset($comment[3]) && $comment[3] === '*'; $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line]; } else { // Invalid characters at the end of the input $badCharTokens = $this->handleInvalidCharacterRange( $filePos, \strlen($this->code), $line, $errorHandler); $this->tokens = array_merge($this->tokens, $badCharTokens); } return; } if (count($this->tokens) > 0) { // Check for unterminated comment $lastToken = $this->tokens[count($this->tokens) - 1]; if ($this->isUnterminatedComment($lastToken)) { $errorHandler->handleError(new Error('Unterminated comment', [ 'startLine' => $line - substr_count($lastToken[1], "\n"), 'endLine' => $line, 'startFilePos' => $filePos - \strlen($lastToken[1]), 'endFilePos' => $filePos, ])); } } } /** * Fetches the next token. * * The available attributes are determined by the 'usedAttributes' option, which can * be specified in the constructor. The following attributes are supported: * * * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances, * representing all comments that occurred between the previous * non-discarded token and the current one. * * 'startLine' => Line in which the node starts. * * 'endLine' => Line in which the node ends. * * 'startTokenPos' => Offset into the token array of the first token in the node. * * 'endTokenPos' => Offset into the token array of the last token in the node. * * 'startFilePos' => Offset into the code string of the first character that is part of the node. * * 'endFilePos' => Offset into the code string of the last character that is part of the node. * * @param mixed $value Variable to store token content in * @param mixed $startAttributes Variable to store start attributes in * @param mixed $endAttributes Variable to store end attributes in * * @return int Token id */ public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int { $startAttributes = []; $endAttributes = []; while (1) { if (isset($this->tokens[++$this->pos])) { $token = $this->tokens[$this->pos]; } else { // EOF token with ID 0 $token = "\0"; } if ($this->attributeStartLineUsed) { $startAttributes['startLine'] = $this->line; } if ($this->attributeStartTokenPosUsed) { $startAttributes['startTokenPos'] = $this->pos; } if ($this->attributeStartFilePosUsed) { $startAttributes['startFilePos'] = $this->filePos; } if (\is_string($token)) { $value = $token; if (isset($token[1])) { // bug in token_get_all $this->filePos += 2; $id = ord('"'); } else { $this->filePos += 1; $id = ord($token); } } elseif (!isset($this->dropTokens[$token[0]])) { $value = $token[1]; $id = $this->tokenMap[$token[0]]; if (\T_CLOSE_TAG === $token[0]) { $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n") || false !== strpos($token[1], "\r"); } elseif (\T_INLINE_HTML === $token[0]) { $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline; } $this->line += substr_count($value, "\n"); $this->filePos += \strlen($value); } else { $origLine = $this->line; $origFilePos = $this->filePos; $this->line += substr_count($token[1], "\n"); $this->filePos += \strlen($token[1]); if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) { if ($this->attributeCommentsUsed) { $comment = \T_DOC_COMMENT === $token[0] ? new Comment\Doc($token[1], $origLine, $origFilePos, $this->pos, $this->line, $this->filePos - 1, $this->pos) : new Comment($token[1], $origLine, $origFilePos, $this->pos, $this->line, $this->filePos - 1, $this->pos); $startAttributes['comments'][] = $comment; } } continue; } if ($this->attributeEndLineUsed) { $endAttributes['endLine'] = $this->line; } if ($this->attributeEndTokenPosUsed) { $endAttributes['endTokenPos'] = $this->pos; } if ($this->attributeEndFilePosUsed) { $endAttributes['endFilePos'] = $this->filePos - 1; } return $id; } throw new \RuntimeException('Reached end of lexer loop'); } /** * Returns the token array for current code. * * The token array is in the same format as provided by the * token_get_all() function and does not discard tokens (i.e. * whitespace and comments are included). The token position * attributes are against this token array. * * @return array Array of tokens in token_get_all() format */ public function getTokens() : array { return $this->tokens; } /** * Handles __halt_compiler() by returning the text after it. * * @return string Remaining text */ public function handleHaltCompiler() : string { // text after T_HALT_COMPILER, still including (); $textAfter = substr($this->code, $this->filePos); // ensure that it is followed by (); // this simplifies the situation, by not allowing any comments // in between of the tokens. if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) { throw new Error('__HALT_COMPILER must be followed by "();"'); } // prevent the lexer from returning any further tokens $this->pos = count($this->tokens); // return with (); removed return substr($textAfter, strlen($matches[0])); } private function defineCompatibilityTokens() { static $compatTokensDefined = false; if ($compatTokensDefined) { return; } $compatTokens = [ // PHP 7.4 'T_BAD_CHARACTER', 'T_FN', 'T_COALESCE_EQUAL', // PHP 8.0 'T_NAME_QUALIFIED', 'T_NAME_FULLY_QUALIFIED', 'T_NAME_RELATIVE', 'T_MATCH', 'T_NULLSAFE_OBJECT_OPERATOR', 'T_ATTRIBUTE', // PHP 8.1 'T_ENUM', 'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', 'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', 'T_READONLY', ]; // PHP-Parser might be used together with another library that also emulates some or all // of these tokens. Perform a sanity-check that all already defined tokens have been // assigned a unique ID. $usedTokenIds = []; foreach ($compatTokens as $token) { if (\defined($token)) { $tokenId = \constant($token); $clashingToken = $usedTokenIds[$tokenId] ?? null; if ($clashingToken !== null) { throw new \Error(sprintf( 'Token %s has same ID as token %s, ' . 'you may be using a library with broken token emulation', $token, $clashingToken )); } $usedTokenIds[$tokenId] = $token; } } // Now define any tokens that have not yet been emulated. Try to assign IDs from -1 // downwards, but skip any IDs that may already be in use. $newTokenId = -1; foreach ($compatTokens as $token) { if (!\defined($token)) { while (isset($usedTokenIds[$newTokenId])) { $newTokenId--; } \define($token, $newTokenId); $newTokenId--; } } $compatTokensDefined = true; } /** * Creates the token map. * * The token map maps the PHP internal token identifiers * to the identifiers used by the Parser. Additionally it * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. * * @return array The token map */ protected function createTokenMap() : array { $tokenMap = []; // 256 is the minimum possible token number, as everything below // it is an ASCII value for ($i = 256; $i < 1000; ++$i) { if (\T_DOUBLE_COLON === $i) { // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM; } elseif(\T_OPEN_TAG_WITH_ECHO === $i) { // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO $tokenMap[$i] = Tokens::T_ECHO; } elseif(\T_CLOSE_TAG === $i) { // T_CLOSE_TAG is equivalent to ';' $tokenMap[$i] = ord(';'); } elseif ('UNKNOWN' !== $name = token_name($i)) { if ('T_HASHBANG' === $name) { // HHVM uses a special token for #! hashbang lines $tokenMap[$i] = Tokens::T_INLINE_HTML; } elseif (defined($name = Tokens::class . '::' . $name)) { // Other tokens can be mapped directly $tokenMap[$i] = constant($name); } } } // HHVM uses a special token for numbers that overflow to double if (defined('T_ONUMBER')) { $tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER; } // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant if (defined('T_COMPILER_HALT_OFFSET')) { $tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING; } // Assign tokens for which we define compatibility constants, as token_name() does not know them. $tokenMap[\T_FN] = Tokens::T_FN; $tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL; $tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED; $tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED; $tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE; $tokenMap[\T_MATCH] = Tokens::T_MATCH; $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR; $tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE; $tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG; $tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG; $tokenMap[\T_ENUM] = Tokens::T_ENUM; $tokenMap[\T_READONLY] = Tokens::T_READONLY; return $tokenMap; } private function createIdentifierTokenMap(): array { // Based on semi_reserved production. return array_fill_keys([ \T_STRING, \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY, \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, \T_MATCH, ], true); } } php-parser/lib/PhpParser/ParserAbstract.php000064400000122346150250175720014744 0ustar00lexer = $lexer; if (isset($options['throwOnError'])) { throw new \LogicException( '"throwOnError" is no longer supported, use "errorHandler" instead'); } $this->initReduceCallbacks(); } /** * Parses PHP code into a node tree. * * If a non-throwing error handler is used, the parser will continue parsing after an error * occurred and attempt to build a partial AST. * * @param string $code The source code to parse * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults * to ErrorHandler\Throwing. * * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and * the parser was unable to recover from an error). */ public function parse(string $code, ErrorHandler $errorHandler = null) { $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing; $this->lexer->startLexing($code, $this->errorHandler); $result = $this->doParse(); // Clear out some of the interior state, so we don't hold onto unnecessary // memory between uses of the parser $this->startAttributeStack = []; $this->endAttributeStack = []; $this->semStack = []; $this->semValue = null; return $result; } protected function doParse() { // We start off with no lookahead-token $symbol = self::SYMBOL_NONE; // The attributes for a node are taken from the first and last token of the node. // From the first token only the startAttributes are taken and from the last only // the endAttributes. Both are merged using the array union operator (+). $startAttributes = []; $endAttributes = []; $this->endAttributes = $endAttributes; // Keep stack of start and end attributes $this->startAttributeStack = []; $this->endAttributeStack = [$endAttributes]; // Start off in the initial state and keep a stack of previous states $state = 0; $stateStack = [$state]; // Semantic value stack (contains values of tokens and semantic action results) $this->semStack = []; // Current position in the stack(s) $stackPos = 0; $this->errorState = 0; for (;;) { //$this->traceNewState($state, $symbol); if ($this->actionBase[$state] === 0) { $rule = $this->actionDefault[$state]; } else { if ($symbol === self::SYMBOL_NONE) { // Fetch the next token id from the lexer and fetch additional info by-ref. // The end attributes are fetched into a temporary variable and only set once the token is really // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is // reduced after a token was read but not yet shifted. $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes); // map the lexer token id to the internally used symbols $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize ? $this->tokenToSymbol[$tokenId] : $this->invalidSymbol; if ($symbol === $this->invalidSymbol) { throw new \RangeException(sprintf( 'The lexer returned an invalid token (id=%d, value=%s)', $tokenId, $tokenValue )); } // Allow productions to access the start attributes of the lookahead token. $this->lookaheadStartAttributes = $startAttributes; //$this->traceRead($symbol); } $idx = $this->actionBase[$state] + $symbol; if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) || ($state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol)) && ($action = $this->action[$idx]) !== $this->defaultAction) { /* * >= numNonLeafStates: shift and reduce * > 0: shift * = 0: accept * < 0: reduce * = -YYUNEXPECTED: error */ if ($action > 0) { /* shift */ //$this->traceShift($symbol); ++$stackPos; $stateStack[$stackPos] = $state = $action; $this->semStack[$stackPos] = $tokenValue; $this->startAttributeStack[$stackPos] = $startAttributes; $this->endAttributeStack[$stackPos] = $endAttributes; $this->endAttributes = $endAttributes; $symbol = self::SYMBOL_NONE; if ($this->errorState) { --$this->errorState; } if ($action < $this->numNonLeafStates) { continue; } /* $yyn >= numNonLeafStates means shift-and-reduce */ $rule = $action - $this->numNonLeafStates; } else { $rule = -$action; } } else { $rule = $this->actionDefault[$state]; } } for (;;) { if ($rule === 0) { /* accept */ //$this->traceAccept(); return $this->semValue; } elseif ($rule !== $this->unexpectedTokenRule) { /* reduce */ //$this->traceReduce($rule); try { $this->reduceCallbacks[$rule]($stackPos); } catch (Error $e) { if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) { $e->setStartLine($startAttributes['startLine']); } $this->emitError($e); // Can't recover from this type of error return null; } /* Goto - shift nonterminal */ $lastEndAttributes = $this->endAttributeStack[$stackPos]; $ruleLength = $this->ruleToLength[$rule]; $stackPos -= $ruleLength; $nonTerminal = $this->ruleToNonTerminal[$rule]; $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos]; if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) { $state = $this->goto[$idx]; } else { $state = $this->gotoDefault[$nonTerminal]; } ++$stackPos; $stateStack[$stackPos] = $state; $this->semStack[$stackPos] = $this->semValue; $this->endAttributeStack[$stackPos] = $lastEndAttributes; if ($ruleLength === 0) { // Empty productions use the start attributes of the lookahead token. $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; } } else { /* error */ switch ($this->errorState) { case 0: $msg = $this->getErrorMessage($symbol, $state); $this->emitError(new Error($msg, $startAttributes + $endAttributes)); // Break missing intentionally case 1: case 2: $this->errorState = 3; // Pop until error-expecting state uncovered while (!( (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) || ($state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) ) || ($action = $this->action[$idx]) === $this->defaultAction) { // Not totally sure about this if ($stackPos <= 0) { // Could not recover from error return null; } $state = $stateStack[--$stackPos]; //$this->tracePop($state); } //$this->traceShift($this->errorSymbol); ++$stackPos; $stateStack[$stackPos] = $state = $action; // We treat the error symbol as being empty, so we reset the end attributes // to the end attributes of the last non-error symbol $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; $this->endAttributeStack[$stackPos] = $this->endAttributeStack[$stackPos - 1]; $this->endAttributes = $this->endAttributeStack[$stackPos - 1]; break; case 3: if ($symbol === 0) { // Reached EOF without recovering from error return null; } //$this->traceDiscard($symbol); $symbol = self::SYMBOL_NONE; break 2; } } if ($state < $this->numNonLeafStates) { break; } /* >= numNonLeafStates means shift-and-reduce */ $rule = $state - $this->numNonLeafStates; } } throw new \RuntimeException('Reached end of parser loop'); } protected function emitError(Error $error) { $this->errorHandler->handleError($error); } /** * Format error message including expected tokens. * * @param int $symbol Unexpected symbol * @param int $state State at time of error * * @return string Formatted error message */ protected function getErrorMessage(int $symbol, int $state) : string { $expectedString = ''; if ($expected = $this->getExpectedTokens($state)) { $expectedString = ', expecting ' . implode(' or ', $expected); } return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; } /** * Get limited number of expected tokens in given state. * * @param int $state State * * @return string[] Expected tokens. If too many, an empty array is returned. */ protected function getExpectedTokens(int $state) : array { $expected = []; $base = $this->actionBase[$state]; foreach ($this->symbolToName as $symbol => $name) { $idx = $base + $symbol; if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol ) { if ($this->action[$idx] !== $this->unexpectedTokenRule && $this->action[$idx] !== $this->defaultAction && $symbol !== $this->errorSymbol ) { if (count($expected) === 4) { /* Too many expected tokens */ return []; } $expected[] = $name; } } } return $expected; } /* * Tracing functions used for debugging the parser. */ /* protected function traceNewState($state, $symbol) { echo '% State ' . $state . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; } protected function traceRead($symbol) { echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; } protected function traceShift($symbol) { echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; } protected function traceAccept() { echo "% Accepted.\n"; } protected function traceReduce($n) { echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; } protected function tracePop($state) { echo '% Recovering, uncovered state ' . $state . "\n"; } protected function traceDiscard($symbol) { echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; } */ /* * Helper functions invoked by semantic actions */ /** * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. * * @param Node\Stmt[] $stmts * @return Node\Stmt[] */ protected function handleNamespaces(array $stmts) : array { $hasErrored = false; $style = $this->getNamespacingStyle($stmts); if (null === $style) { // not namespaced, nothing to do return $stmts; } elseif ('brace' === $style) { // For braced namespaces we only have to check that there are no invalid statements between the namespaces $afterFirstNamespace = false; foreach ($stmts as $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { $afterFirstNamespace = true; } elseif (!$stmt instanceof Node\Stmt\HaltCompiler && !$stmt instanceof Node\Stmt\Nop && $afterFirstNamespace && !$hasErrored) { $this->emitError(new Error( 'No code may exist outside of namespace {}', $stmt->getAttributes())); $hasErrored = true; // Avoid one error for every statement } } return $stmts; } else { // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts $resultStmts = []; $targetStmts =& $resultStmts; $lastNs = null; foreach ($stmts as $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { if ($lastNs !== null) { $this->fixupNamespaceAttributes($lastNs); } if ($stmt->stmts === null) { $stmt->stmts = []; $targetStmts =& $stmt->stmts; $resultStmts[] = $stmt; } else { // This handles the invalid case of mixed style namespaces $resultStmts[] = $stmt; $targetStmts =& $resultStmts; } $lastNs = $stmt; } elseif ($stmt instanceof Node\Stmt\HaltCompiler) { // __halt_compiler() is not moved into the namespace $resultStmts[] = $stmt; } else { $targetStmts[] = $stmt; } } if ($lastNs !== null) { $this->fixupNamespaceAttributes($lastNs); } return $resultStmts; } } private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt) { // We moved the statements into the namespace node, as such the end of the namespace node // needs to be extended to the end of the statements. if (empty($stmt->stmts)) { return; } // We only move the builtin end attributes here. This is the best we can do with the // knowledge we have. $endAttributes = ['endLine', 'endFilePos', 'endTokenPos']; $lastStmt = $stmt->stmts[count($stmt->stmts) - 1]; foreach ($endAttributes as $endAttribute) { if ($lastStmt->hasAttribute($endAttribute)) { $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute)); } } } /** * Determine namespacing style (semicolon or brace) * * @param Node[] $stmts Top-level statements. * * @return null|string One of "semicolon", "brace" or null (no namespaces) */ private function getNamespacingStyle(array $stmts) { $style = null; $hasNotAllowedStmts = false; foreach ($stmts as $i => $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; if (null === $style) { $style = $currentStyle; if ($hasNotAllowedStmts) { $this->emitError(new Error( 'Namespace declaration statement has to be the very first statement in the script', $stmt->getLine() // Avoid marking the entire namespace as an error )); } } elseif ($style !== $currentStyle) { $this->emitError(new Error( 'Cannot mix bracketed namespace declarations with unbracketed namespace declarations', $stmt->getLine() // Avoid marking the entire namespace as an error )); // Treat like semicolon style for namespace normalization return 'semicolon'; } continue; } /* declare(), __halt_compiler() and nops can be used before a namespace declaration */ if ($stmt instanceof Node\Stmt\Declare_ || $stmt instanceof Node\Stmt\HaltCompiler || $stmt instanceof Node\Stmt\Nop) { continue; } /* There may be a hashbang line at the very start of the file */ if ($i === 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) { continue; } /* Everything else if forbidden before namespace declarations */ $hasNotAllowedStmts = true; } return $style; } /** * Fix up parsing of static property calls in PHP 5. * * In PHP 5 A::$b[c][d] and A::$b[c][d]() have very different interpretation. The former is * interpreted as (A::$b)[c][d], while the latter is the same as A::{$b[c][d]}(). We parse the * latter as the former initially and this method fixes the AST into the correct form when we * encounter the "()". * * @param Node\Expr\StaticPropertyFetch|Node\Expr\ArrayDimFetch $prop * @param Node\Arg[] $args * @param array $attributes * * @return Expr\StaticCall */ protected function fixupPhp5StaticPropCall($prop, array $args, array $attributes) : Expr\StaticCall { if ($prop instanceof Node\Expr\StaticPropertyFetch) { $name = $prop->name instanceof VarLikeIdentifier ? $prop->name->toString() : $prop->name; $var = new Expr\Variable($name, $prop->name->getAttributes()); return new Expr\StaticCall($prop->class, $var, $args, $attributes); } elseif ($prop instanceof Node\Expr\ArrayDimFetch) { $tmp = $prop; while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { $tmp = $tmp->var; } /** @var Expr\StaticPropertyFetch $staticProp */ $staticProp = $tmp->var; // Set start attributes to attributes of innermost node $tmp = $prop; $this->fixupStartAttributes($tmp, $staticProp->name); while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { $tmp = $tmp->var; $this->fixupStartAttributes($tmp, $staticProp->name); } $name = $staticProp->name instanceof VarLikeIdentifier ? $staticProp->name->toString() : $staticProp->name; $tmp->var = new Expr\Variable($name, $staticProp->name->getAttributes()); return new Expr\StaticCall($staticProp->class, $prop, $args, $attributes); } else { throw new \Exception; } } protected function fixupStartAttributes(Node $to, Node $from) { $startAttributes = ['startLine', 'startFilePos', 'startTokenPos']; foreach ($startAttributes as $startAttribute) { if ($from->hasAttribute($startAttribute)) { $to->setAttribute($startAttribute, $from->getAttribute($startAttribute)); } } } protected function handleBuiltinTypes(Name $name) { $builtinTypes = [ 'bool' => true, 'int' => true, 'float' => true, 'string' => true, 'iterable' => true, 'void' => true, 'object' => true, 'null' => true, 'false' => true, 'mixed' => true, 'never' => true, 'true' => true, ]; if (!$name->isUnqualified()) { return $name; } $lowerName = $name->toLowerString(); if (!isset($builtinTypes[$lowerName])) { return $name; } return new Node\Identifier($lowerName, $name->getAttributes()); } /** * Get combined start and end attributes at a stack location * * @param int $pos Stack location * * @return array Combined start and end attributes */ protected function getAttributesAt(int $pos) : array { return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; } protected function getFloatCastKind(string $cast): int { $cast = strtolower($cast); if (strpos($cast, 'float') !== false) { return Double::KIND_FLOAT; } if (strpos($cast, 'real') !== false) { return Double::KIND_REAL; } return Double::KIND_DOUBLE; } protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) { try { return LNumber::fromString($str, $attributes, $allowInvalidOctal); } catch (Error $error) { $this->emitError($error); // Use dummy value return new LNumber(0, $attributes); } } /** * Parse a T_NUM_STRING token into either an integer or string node. * * @param string $str Number string * @param array $attributes Attributes * * @return LNumber|String_ Integer or string node. */ protected function parseNumString(string $str, array $attributes) { if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) { return new String_($str, $attributes); } $num = +$str; if (!is_int($num)) { return new String_($str, $attributes); } return new LNumber($num, $attributes); } protected function stripIndentation( string $string, int $indentLen, string $indentChar, bool $newlineAtStart, bool $newlineAtEnd, array $attributes ) { if ($indentLen === 0) { return $string; } $start = $newlineAtStart ? '(?:(?<=\n)|\A)' : '(?<=\n)'; $end = $newlineAtEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])'; $regex = '/' . $start . '([ \t]*)(' . $end . ')?/'; return preg_replace_callback( $regex, function ($matches) use ($indentLen, $indentChar, $attributes) { $prefix = substr($matches[1], 0, $indentLen); if (false !== strpos($prefix, $indentChar === " " ? "\t" : " ")) { $this->emitError(new Error( 'Invalid indentation - tabs and spaces cannot be mixed', $attributes )); } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) { $this->emitError(new Error( 'Invalid body indentation level ' . '(expecting an indentation level of at least ' . $indentLen . ')', $attributes )); } return substr($matches[0], strlen($prefix)); }, $string ); } protected function parseDocString( string $startToken, $contents, string $endToken, array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape ) { $kind = strpos($startToken, "'") === false ? String_::KIND_HEREDOC : String_::KIND_NOWDOC; $regex = '/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/'; $result = preg_match($regex, $startToken, $matches); assert($result === 1); $label = $matches[1]; $result = preg_match('/\A[ \t]*/', $endToken, $matches); assert($result === 1); $indentation = $matches[0]; $attributes['kind'] = $kind; $attributes['docLabel'] = $label; $attributes['docIndentation'] = $indentation; $indentHasSpaces = false !== strpos($indentation, " "); $indentHasTabs = false !== strpos($indentation, "\t"); if ($indentHasSpaces && $indentHasTabs) { $this->emitError(new Error( 'Invalid indentation - tabs and spaces cannot be mixed', $endTokenAttributes )); // Proceed processing as if this doc string is not indented $indentation = ''; } $indentLen = \strlen($indentation); $indentChar = $indentHasSpaces ? " " : "\t"; if (\is_string($contents)) { if ($contents === '') { return new String_('', $attributes); } $contents = $this->stripIndentation( $contents, $indentLen, $indentChar, true, true, $attributes ); $contents = preg_replace('~(\r\n|\n|\r)\z~', '', $contents); if ($kind === String_::KIND_HEREDOC) { $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape); } return new String_($contents, $attributes); } else { assert(count($contents) > 0); if (!$contents[0] instanceof Node\Scalar\EncapsedStringPart) { // If there is no leading encapsed string part, pretend there is an empty one $this->stripIndentation( '', $indentLen, $indentChar, true, false, $contents[0]->getAttributes() ); } $newContents = []; foreach ($contents as $i => $part) { if ($part instanceof Node\Scalar\EncapsedStringPart) { $isLast = $i === \count($contents) - 1; $part->value = $this->stripIndentation( $part->value, $indentLen, $indentChar, $i === 0, $isLast, $part->getAttributes() ); $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape); if ($isLast) { $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value); } if ('' === $part->value) { continue; } } $newContents[] = $part; } return new Encapsed($newContents, $attributes); } } /** * Create attributes for a zero-length common-capturing nop. * * @param Comment[] $comments * @return array */ protected function createCommentNopAttributes(array $comments) { $comment = $comments[count($comments) - 1]; $commentEndLine = $comment->getEndLine(); $commentEndFilePos = $comment->getEndFilePos(); $commentEndTokenPos = $comment->getEndTokenPos(); $attributes = ['comments' => $comments]; if (-1 !== $commentEndLine) { $attributes['startLine'] = $commentEndLine; $attributes['endLine'] = $commentEndLine; } if (-1 !== $commentEndFilePos) { $attributes['startFilePos'] = $commentEndFilePos + 1; $attributes['endFilePos'] = $commentEndFilePos; } if (-1 !== $commentEndTokenPos) { $attributes['startTokenPos'] = $commentEndTokenPos + 1; $attributes['endTokenPos'] = $commentEndTokenPos; } return $attributes; } /** @param ElseIf_|Else_ $node */ protected function fixupAlternativeElse($node) { // Make sure a trailing nop statement carrying comments is part of the node. $numStmts = \count($node->stmts); if ($numStmts !== 0 && $node->stmts[$numStmts - 1] instanceof Nop) { $nopAttrs = $node->stmts[$numStmts - 1]->getAttributes(); if (isset($nopAttrs['endLine'])) { $node->setAttribute('endLine', $nopAttrs['endLine']); } if (isset($nopAttrs['endFilePos'])) { $node->setAttribute('endFilePos', $nopAttrs['endFilePos']); } if (isset($nopAttrs['endTokenPos'])) { $node->setAttribute('endTokenPos', $nopAttrs['endTokenPos']); } } } protected function checkClassModifier($a, $b, $modifierPos) { try { Class_::verifyClassModifier($a, $b); } catch (Error $error) { $error->setAttributes($this->getAttributesAt($modifierPos)); $this->emitError($error); } } protected function checkModifier($a, $b, $modifierPos) { // Jumping through some hoops here because verifyModifier() is also used elsewhere try { Class_::verifyModifier($a, $b); } catch (Error $error) { $error->setAttributes($this->getAttributesAt($modifierPos)); $this->emitError($error); } } protected function checkParam(Param $node) { if ($node->variadic && null !== $node->default) { $this->emitError(new Error( 'Variadic parameter cannot have a default value', $node->default->getAttributes() )); } } protected function checkTryCatch(TryCatch $node) { if (empty($node->catches) && null === $node->finally) { $this->emitError(new Error( 'Cannot use try without catch or finally', $node->getAttributes() )); } } protected function checkNamespace(Namespace_ $node) { if (null !== $node->stmts) { foreach ($node->stmts as $stmt) { if ($stmt instanceof Namespace_) { $this->emitError(new Error( 'Namespace declarations cannot be nested', $stmt->getAttributes() )); } } } } private function checkClassName($name, $namePos) { if (null !== $name && $name->isSpecialClassName()) { $this->emitError(new Error( sprintf('Cannot use \'%s\' as class name as it is reserved', $name), $this->getAttributesAt($namePos) )); } } private function checkImplementedInterfaces(array $interfaces) { foreach ($interfaces as $interface) { if ($interface->isSpecialClassName()) { $this->emitError(new Error( sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), $interface->getAttributes() )); } } } protected function checkClass(Class_ $node, $namePos) { $this->checkClassName($node->name, $namePos); if ($node->extends && $node->extends->isSpecialClassName()) { $this->emitError(new Error( sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), $node->extends->getAttributes() )); } $this->checkImplementedInterfaces($node->implements); } protected function checkInterface(Interface_ $node, $namePos) { $this->checkClassName($node->name, $namePos); $this->checkImplementedInterfaces($node->extends); } protected function checkEnum(Enum_ $node, $namePos) { $this->checkClassName($node->name, $namePos); $this->checkImplementedInterfaces($node->implements); } protected function checkClassMethod(ClassMethod $node, $modifierPos) { if ($node->flags & Class_::MODIFIER_STATIC) { switch ($node->name->toLowerString()) { case '__construct': $this->emitError(new Error( sprintf('Constructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; case '__destruct': $this->emitError(new Error( sprintf('Destructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; case '__clone': $this->emitError(new Error( sprintf('Clone method %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; } } if ($node->flags & Class_::MODIFIER_READONLY) { $this->emitError(new Error( sprintf('Method %s() cannot be readonly', $node->name), $this->getAttributesAt($modifierPos))); } } protected function checkClassConst(ClassConst $node, $modifierPos) { if ($node->flags & Class_::MODIFIER_STATIC) { $this->emitError(new Error( "Cannot use 'static' as constant modifier", $this->getAttributesAt($modifierPos))); } if ($node->flags & Class_::MODIFIER_ABSTRACT) { $this->emitError(new Error( "Cannot use 'abstract' as constant modifier", $this->getAttributesAt($modifierPos))); } if ($node->flags & Class_::MODIFIER_READONLY) { $this->emitError(new Error( "Cannot use 'readonly' as constant modifier", $this->getAttributesAt($modifierPos))); } } protected function checkProperty(Property $node, $modifierPos) { if ($node->flags & Class_::MODIFIER_ABSTRACT) { $this->emitError(new Error('Properties cannot be declared abstract', $this->getAttributesAt($modifierPos))); } if ($node->flags & Class_::MODIFIER_FINAL) { $this->emitError(new Error('Properties cannot be declared final', $this->getAttributesAt($modifierPos))); } } protected function checkUseUse(UseUse $node, $namePos) { if ($node->alias && $node->alias->isSpecialClassName()) { $this->emitError(new Error( sprintf( 'Cannot use %s as %s because \'%2$s\' is a special class name', $node->name, $node->alias ), $this->getAttributesAt($namePos) )); } } } php-parser/lib/PhpParser/NodeTraverser.php000064400000024540150250175720014604 0ustar00visitors[] = $visitor; } /** * Removes an added visitor. * * @param NodeVisitor $visitor */ public function removeVisitor(NodeVisitor $visitor) { foreach ($this->visitors as $index => $storedVisitor) { if ($storedVisitor === $visitor) { unset($this->visitors[$index]); break; } } } /** * Traverses an array of nodes using the registered visitors. * * @param Node[] $nodes Array of nodes * * @return Node[] Traversed array of nodes */ public function traverse(array $nodes) : array { $this->stopTraversal = false; foreach ($this->visitors as $visitor) { if (null !== $return = $visitor->beforeTraverse($nodes)) { $nodes = $return; } } $nodes = $this->traverseArray($nodes); foreach ($this->visitors as $visitor) { if (null !== $return = $visitor->afterTraverse($nodes)) { $nodes = $return; } } return $nodes; } /** * Recursively traverse a node. * * @param Node $node Node to traverse. * * @return Node Result of traversal (may be original node or new one) */ protected function traverseNode(Node $node) : Node { foreach ($node->getSubNodeNames() as $name) { $subNode =& $node->$name; if (\is_array($subNode)) { $subNode = $this->traverseArray($subNode); if ($this->stopTraversal) { break; } } elseif ($subNode instanceof Node) { $traverseChildren = true; $breakVisitorIndex = null; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($subNode); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $return; } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = false; } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { $traverseChildren = false; $breakVisitorIndex = $visitorIndex; break; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } else { throw new \LogicException( 'enterNode() returned invalid value of type ' . gettype($return) ); } } } if ($traverseChildren) { $subNode = $this->traverseNode($subNode); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->leaveNode($subNode); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $return; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } elseif (\is_array($return)) { throw new \LogicException( 'leaveNode() may only return an array ' . 'if the parent structure is an array' ); } else { throw new \LogicException( 'leaveNode() returned invalid value of type ' . gettype($return) ); } } if ($breakVisitorIndex === $visitorIndex) { break; } } } } return $node; } /** * Recursively traverse array (usually of nodes). * * @param array $nodes Array to traverse * * @return array Result of traversal (may be original array or changed one) */ protected function traverseArray(array $nodes) : array { $doNodes = []; foreach ($nodes as $i => &$node) { if ($node instanceof Node) { $traverseChildren = true; $breakVisitorIndex = null; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($node); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($node, $return); $node = $return; } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = false; } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { $traverseChildren = false; $breakVisitorIndex = $visitorIndex; break; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } else { throw new \LogicException( 'enterNode() returned invalid value of type ' . gettype($return) ); } } } if ($traverseChildren) { $node = $this->traverseNode($node); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->leaveNode($node); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($node, $return); $node = $return; } elseif (\is_array($return)) { $doNodes[] = [$i, $return]; break; } elseif (self::REMOVE_NODE === $return) { $doNodes[] = [$i, []]; break; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } elseif (false === $return) { throw new \LogicException( 'bool(false) return from leaveNode() no longer supported. ' . 'Return NodeTraverser::REMOVE_NODE instead' ); } else { throw new \LogicException( 'leaveNode() returned invalid value of type ' . gettype($return) ); } } if ($breakVisitorIndex === $visitorIndex) { break; } } } elseif (\is_array($node)) { throw new \LogicException('Invalid node structure: Contains nested arrays'); } } if (!empty($doNodes)) { while (list($i, $replace) = array_pop($doNodes)) { array_splice($nodes, $i, 1, $replace); } } return $nodes; } private function ensureReplacementReasonable($old, $new) { if ($old instanceof Node\Stmt && $new instanceof Node\Expr) { throw new \LogicException( "Trying to replace statement ({$old->getType()}) " . "with expression ({$new->getType()}). Are you missing a " . "Stmt_Expression wrapper?" ); } if ($old instanceof Node\Expr && $new instanceof Node\Stmt) { throw new \LogicException( "Trying to replace expression ({$old->getType()}) " . "with statement ({$new->getType()})" ); } } } php-parser/lib/PhpParser/Node.php000064400000007607150250175720012713 0ustar00pAttrGroups($node->attrGroups, true) . $this->pModifiers($node->flags) . ($node->type ? $this->p($node->type) . ' ' : '') . ($node->byRef ? '&' : '') . ($node->variadic ? '...' : '') . $this->p($node->var) . ($node->default ? ' = ' . $this->p($node->default) : ''); } protected function pArg(Node\Arg $node) { return ($node->name ? $node->name->toString() . ': ' : '') . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); } protected function pVariadicPlaceholder(Node\VariadicPlaceholder $node) { return '...'; } protected function pConst(Node\Const_ $node) { return $node->name . ' = ' . $this->p($node->value); } protected function pNullableType(Node\NullableType $node) { return '?' . $this->p($node->type); } protected function pUnionType(Node\UnionType $node) { $types = []; foreach ($node->types as $typeNode) { if ($typeNode instanceof Node\IntersectionType) { $types[] = '('. $this->p($typeNode) . ')'; continue; } $types[] = $this->p($typeNode); } return implode('|', $types); } protected function pIntersectionType(Node\IntersectionType $node) { return $this->pImplode($node->types, '&'); } protected function pIdentifier(Node\Identifier $node) { return $node->name; } protected function pVarLikeIdentifier(Node\VarLikeIdentifier $node) { return '$' . $node->name; } protected function pAttribute(Node\Attribute $node) { return $this->p($node->name) . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : ''); } protected function pAttributeGroup(Node\AttributeGroup $node) { return '#[' . $this->pCommaSeparated($node->attrs) . ']'; } // Names protected function pName(Name $node) { return implode('\\', $node->parts); } protected function pName_FullyQualified(Name\FullyQualified $node) { return '\\' . implode('\\', $node->parts); } protected function pName_Relative(Name\Relative $node) { return 'namespace\\' . implode('\\', $node->parts); } // Magic Constants protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) { return '__CLASS__'; } protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) { return '__DIR__'; } protected function pScalar_MagicConst_File(MagicConst\File $node) { return '__FILE__'; } protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) { return '__FUNCTION__'; } protected function pScalar_MagicConst_Line(MagicConst\Line $node) { return '__LINE__'; } protected function pScalar_MagicConst_Method(MagicConst\Method $node) { return '__METHOD__'; } protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) { return '__NAMESPACE__'; } protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) { return '__TRAIT__'; } // Scalars protected function pScalar_String(Scalar\String_ $node) { $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED); switch ($kind) { case Scalar\String_::KIND_NOWDOC: $label = $node->getAttribute('docLabel'); if ($label && !$this->containsEndLabel($node->value, $label)) { if ($node->value === '') { return "<<<'$label'\n$label" . $this->docStringEndToken; } return "<<<'$label'\n$node->value\n$label" . $this->docStringEndToken; } /* break missing intentionally */ case Scalar\String_::KIND_SINGLE_QUOTED: return $this->pSingleQuotedString($node->value); case Scalar\String_::KIND_HEREDOC: $label = $node->getAttribute('docLabel'); if ($label && !$this->containsEndLabel($node->value, $label)) { if ($node->value === '') { return "<<<$label\n$label" . $this->docStringEndToken; } $escaped = $this->escapeString($node->value, null); return "<<<$label\n" . $escaped . "\n$label" . $this->docStringEndToken; } /* break missing intentionally */ case Scalar\String_::KIND_DOUBLE_QUOTED: return '"' . $this->escapeString($node->value, '"') . '"'; } throw new \Exception('Invalid string kind'); } protected function pScalar_Encapsed(Scalar\Encapsed $node) { if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) { $label = $node->getAttribute('docLabel'); if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { if (count($node->parts) === 1 && $node->parts[0] instanceof Scalar\EncapsedStringPart && $node->parts[0]->value === '' ) { return "<<<$label\n$label" . $this->docStringEndToken; } return "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label" . $this->docStringEndToken; } } return '"' . $this->pEncapsList($node->parts, '"') . '"'; } protected function pScalar_LNumber(Scalar\LNumber $node) { if ($node->value === -\PHP_INT_MAX-1) { // PHP_INT_MIN cannot be represented as a literal, // because the sign is not part of the literal return '(-' . \PHP_INT_MAX . '-1)'; } $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC); if (Scalar\LNumber::KIND_DEC === $kind) { return (string) $node->value; } if ($node->value < 0) { $sign = '-'; $str = (string) -$node->value; } else { $sign = ''; $str = (string) $node->value; } switch ($kind) { case Scalar\LNumber::KIND_BIN: return $sign . '0b' . base_convert($str, 10, 2); case Scalar\LNumber::KIND_OCT: return $sign . '0' . base_convert($str, 10, 8); case Scalar\LNumber::KIND_HEX: return $sign . '0x' . base_convert($str, 10, 16); } throw new \Exception('Invalid number kind'); } protected function pScalar_DNumber(Scalar\DNumber $node) { if (!is_finite($node->value)) { if ($node->value === \INF) { return '\INF'; } elseif ($node->value === -\INF) { return '-\INF'; } else { return '\NAN'; } } // Try to find a short full-precision representation $stringValue = sprintf('%.16G', $node->value); if ($node->value !== (double) $stringValue) { $stringValue = sprintf('%.17G', $node->value); } // %G is locale dependent and there exists no locale-independent alternative. We don't want // mess with switching locales here, so let's assume that a comma is the only non-standard // decimal separator we may encounter... $stringValue = str_replace(',', '.', $stringValue); // ensure that number is really printed as float return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; } protected function pScalar_EncapsedStringPart(Scalar\EncapsedStringPart $node) { throw new \LogicException('Cannot directly print EncapsedStringPart'); } // Assignments protected function pExpr_Assign(Expr\Assign $node) { return $this->pInfixOp(Expr\Assign::class, $node->var, ' = ', $node->expr); } protected function pExpr_AssignRef(Expr\AssignRef $node) { return $this->pInfixOp(Expr\AssignRef::class, $node->var, ' =& ', $node->expr); } protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) { return $this->pInfixOp(AssignOp\Plus::class, $node->var, ' += ', $node->expr); } protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) { return $this->pInfixOp(AssignOp\Minus::class, $node->var, ' -= ', $node->expr); } protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) { return $this->pInfixOp(AssignOp\Mul::class, $node->var, ' *= ', $node->expr); } protected function pExpr_AssignOp_Div(AssignOp\Div $node) { return $this->pInfixOp(AssignOp\Div::class, $node->var, ' /= ', $node->expr); } protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) { return $this->pInfixOp(AssignOp\Concat::class, $node->var, ' .= ', $node->expr); } protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) { return $this->pInfixOp(AssignOp\Mod::class, $node->var, ' %= ', $node->expr); } protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { return $this->pInfixOp(AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr); } protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { return $this->pInfixOp(AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr); } protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { return $this->pInfixOp(AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr); } protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { return $this->pInfixOp(AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr); } protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { return $this->pInfixOp(AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr); } protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) { return $this->pInfixOp(AssignOp\Pow::class, $node->var, ' **= ', $node->expr); } protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node) { return $this->pInfixOp(AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr); } // Binary expressions protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) { return $this->pInfixOp(BinaryOp\Plus::class, $node->left, ' + ', $node->right); } protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) { return $this->pInfixOp(BinaryOp\Minus::class, $node->left, ' - ', $node->right); } protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) { return $this->pInfixOp(BinaryOp\Mul::class, $node->left, ' * ', $node->right); } protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) { return $this->pInfixOp(BinaryOp\Div::class, $node->left, ' / ', $node->right); } protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) { return $this->pInfixOp(BinaryOp\Concat::class, $node->left, ' . ', $node->right); } protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) { return $this->pInfixOp(BinaryOp\Mod::class, $node->left, ' % ', $node->right); } protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) { return $this->pInfixOp(BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right); } protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) { return $this->pInfixOp(BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right); } protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) { return $this->pInfixOp(BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right); } protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) { return $this->pInfixOp(BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right); } protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) { return $this->pInfixOp(BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right); } protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) { return $this->pInfixOp(BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right); } protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) { return $this->pInfixOp(BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right); } protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) { return $this->pInfixOp(BinaryOp\Pow::class, $node->left, ' ** ', $node->right); } protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) { return $this->pInfixOp(BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right); } protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) { return $this->pInfixOp(BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right); } protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) { return $this->pInfixOp(BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right); } protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) { return $this->pInfixOp(BinaryOp\Equal::class, $node->left, ' == ', $node->right); } protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) { return $this->pInfixOp(BinaryOp\NotEqual::class, $node->left, ' != ', $node->right); } protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) { return $this->pInfixOp(BinaryOp\Identical::class, $node->left, ' === ', $node->right); } protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) { return $this->pInfixOp(BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right); } protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) { return $this->pInfixOp(BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right); } protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) { return $this->pInfixOp(BinaryOp\Greater::class, $node->left, ' > ', $node->right); } protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) { return $this->pInfixOp(BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right); } protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) { return $this->pInfixOp(BinaryOp\Smaller::class, $node->left, ' < ', $node->right); } protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) { return $this->pInfixOp(BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right); } protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) { return $this->pInfixOp(BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right); } protected function pExpr_Instanceof(Expr\Instanceof_ $node) { list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class]; return $this->pPrec($node->expr, $precedence, $associativity, -1) . ' instanceof ' . $this->pNewVariable($node->class); } // Unary expressions protected function pExpr_BooleanNot(Expr\BooleanNot $node) { return $this->pPrefixOp(Expr\BooleanNot::class, '!', $node->expr); } protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) { return $this->pPrefixOp(Expr\BitwiseNot::class, '~', $node->expr); } protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) { if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) { // Enforce -(-$expr) instead of --$expr return '-(' . $this->p($node->expr) . ')'; } return $this->pPrefixOp(Expr\UnaryMinus::class, '-', $node->expr); } protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) { if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) { // Enforce +(+$expr) instead of ++$expr return '+(' . $this->p($node->expr) . ')'; } return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr); } protected function pExpr_PreInc(Expr\PreInc $node) { return $this->pPrefixOp(Expr\PreInc::class, '++', $node->var); } protected function pExpr_PreDec(Expr\PreDec $node) { return $this->pPrefixOp(Expr\PreDec::class, '--', $node->var); } protected function pExpr_PostInc(Expr\PostInc $node) { return $this->pPostfixOp(Expr\PostInc::class, $node->var, '++'); } protected function pExpr_PostDec(Expr\PostDec $node) { return $this->pPostfixOp(Expr\PostDec::class, $node->var, '--'); } protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) { return $this->pPrefixOp(Expr\ErrorSuppress::class, '@', $node->expr); } protected function pExpr_YieldFrom(Expr\YieldFrom $node) { return $this->pPrefixOp(Expr\YieldFrom::class, 'yield from ', $node->expr); } protected function pExpr_Print(Expr\Print_ $node) { return $this->pPrefixOp(Expr\Print_::class, 'print ', $node->expr); } // Casts protected function pExpr_Cast_Int(Cast\Int_ $node) { return $this->pPrefixOp(Cast\Int_::class, '(int) ', $node->expr); } protected function pExpr_Cast_Double(Cast\Double $node) { $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE); if ($kind === Cast\Double::KIND_DOUBLE) { $cast = '(double)'; } elseif ($kind === Cast\Double::KIND_FLOAT) { $cast = '(float)'; } elseif ($kind === Cast\Double::KIND_REAL) { $cast = '(real)'; } return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr); } protected function pExpr_Cast_String(Cast\String_ $node) { return $this->pPrefixOp(Cast\String_::class, '(string) ', $node->expr); } protected function pExpr_Cast_Array(Cast\Array_ $node) { return $this->pPrefixOp(Cast\Array_::class, '(array) ', $node->expr); } protected function pExpr_Cast_Object(Cast\Object_ $node) { return $this->pPrefixOp(Cast\Object_::class, '(object) ', $node->expr); } protected function pExpr_Cast_Bool(Cast\Bool_ $node) { return $this->pPrefixOp(Cast\Bool_::class, '(bool) ', $node->expr); } protected function pExpr_Cast_Unset(Cast\Unset_ $node) { return $this->pPrefixOp(Cast\Unset_::class, '(unset) ', $node->expr); } // Function calls and similar constructs protected function pExpr_FuncCall(Expr\FuncCall $node) { return $this->pCallLhs($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_MethodCall(Expr\MethodCall $node) { return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node) { return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_StaticCall(Expr\StaticCall $node) { return $this->pDereferenceLhs($node->class) . '::' . ($node->name instanceof Expr ? ($node->name instanceof Expr\Variable ? $this->p($node->name) : '{' . $this->p($node->name) . '}') : $node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_Empty(Expr\Empty_ $node) { return 'empty(' . $this->p($node->expr) . ')'; } protected function pExpr_Isset(Expr\Isset_ $node) { return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; } protected function pExpr_Eval(Expr\Eval_ $node) { return 'eval(' . $this->p($node->expr) . ')'; } protected function pExpr_Include(Expr\Include_ $node) { static $map = [ Expr\Include_::TYPE_INCLUDE => 'include', Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', Expr\Include_::TYPE_REQUIRE => 'require', Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', ]; return $map[$node->type] . ' ' . $this->p($node->expr); } protected function pExpr_List(Expr\List_ $node) { return 'list(' . $this->pCommaSeparated($node->items) . ')'; } // Other protected function pExpr_Error(Expr\Error $node) { throw new \LogicException('Cannot pretty-print AST with Error nodes'); } protected function pExpr_Variable(Expr\Variable $node) { if ($node->name instanceof Expr) { return '${' . $this->p($node->name) . '}'; } else { return '$' . $node->name; } } protected function pExpr_Array(Expr\Array_ $node) { $syntax = $node->getAttribute('kind', $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG); if ($syntax === Expr\Array_::KIND_SHORT) { return '[' . $this->pMaybeMultiline($node->items, true) . ']'; } else { return 'array(' . $this->pMaybeMultiline($node->items, true) . ')'; } } protected function pExpr_ArrayItem(Expr\ArrayItem $node) { return (null !== $node->key ? $this->p($node->key) . ' => ' : '') . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); } protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) { return $this->pDereferenceLhs($node->var) . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; } protected function pExpr_ConstFetch(Expr\ConstFetch $node) { return $this->p($node->name); } protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) { return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name); } protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) { return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); } protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node) { return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name); } protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) { return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); } protected function pExpr_ShellExec(Expr\ShellExec $node) { return '`' . $this->pEncapsList($node->parts, '`') . '`'; } protected function pExpr_Closure(Expr\Closure $node) { return $this->pAttrGroups($node->attrGroups, true) . ($node->static ? 'static ' : '') . 'function ' . ($node->byRef ? '&' : '') . '(' . $this->pCommaSeparated($node->params) . ')' . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '') . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pExpr_Match(Expr\Match_ $node) { return 'match (' . $this->p($node->cond) . ') {' . $this->pCommaSeparatedMultiline($node->arms, true) . $this->nl . '}'; } protected function pMatchArm(Node\MatchArm $node) { return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default') . ' => ' . $this->p($node->body); } protected function pExpr_ArrowFunction(Expr\ArrowFunction $node) { return $this->pAttrGroups($node->attrGroups, true) . ($node->static ? 'static ' : '') . 'fn' . ($node->byRef ? '&' : '') . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') . ' => ' . $this->p($node->expr); } protected function pExpr_ClosureUse(Expr\ClosureUse $node) { return ($node->byRef ? '&' : '') . $this->p($node->var); } protected function pExpr_New(Expr\New_ $node) { if ($node->class instanceof Stmt\Class_) { $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; return 'new ' . $this->pClassCommon($node->class, $args); } return 'new ' . $this->pNewVariable($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_Clone(Expr\Clone_ $node) { return 'clone ' . $this->p($node->expr); } protected function pExpr_Ternary(Expr\Ternary $node) { // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. // this is okay because the part between ? and : never needs parentheses. return $this->pInfixOp(Expr\Ternary::class, $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else ); } protected function pExpr_Exit(Expr\Exit_ $node) { $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE); return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); } protected function pExpr_Throw(Expr\Throw_ $node) { return 'throw ' . $this->p($node->expr); } protected function pExpr_Yield(Expr\Yield_ $node) { if ($node->value === null) { return 'yield'; } else { // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary return '(yield ' . ($node->key !== null ? $this->p($node->key) . ' => ' : '') . $this->p($node->value) . ')'; } } // Declarations protected function pStmt_Namespace(Stmt\Namespace_ $node) { if ($this->canUseSemicolonNamespaces) { return 'namespace ' . $this->p($node->name) . ';' . $this->nl . $this->pStmts($node->stmts, false); } else { return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; } } protected function pStmt_Use(Stmt\Use_ $node) { return 'use ' . $this->pUseType($node->type) . $this->pCommaSeparated($node->uses) . ';'; } protected function pStmt_GroupUse(Stmt\GroupUse $node) { return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) . '\{' . $this->pCommaSeparated($node->uses) . '};'; } protected function pStmt_UseUse(Stmt\UseUse $node) { return $this->pUseType($node->type) . $this->p($node->name) . (null !== $node->alias ? ' as ' . $node->alias : ''); } protected function pUseType($type) { return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); } protected function pStmt_Interface(Stmt\Interface_ $node) { return $this->pAttrGroups($node->attrGroups) . 'interface ' . $node->name . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Enum(Stmt\Enum_ $node) { return $this->pAttrGroups($node->attrGroups) . 'enum ' . $node->name . ($node->scalarType ? " : $node->scalarType" : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Class(Stmt\Class_ $node) { return $this->pClassCommon($node, ' ' . $node->name); } protected function pStmt_Trait(Stmt\Trait_ $node) { return $this->pAttrGroups($node->attrGroups) . 'trait ' . $node->name . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_EnumCase(Stmt\EnumCase $node) { return $this->pAttrGroups($node->attrGroups) . 'case ' . $node->name . ($node->expr ? ' = ' . $this->p($node->expr) : '') . ';'; } protected function pStmt_TraitUse(Stmt\TraitUse $node) { return 'use ' . $this->pCommaSeparated($node->traits) . (empty($node->adaptations) ? ';' : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}'); } protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) { return $this->p($node->trait) . '::' . $node->method . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; } protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) { return (null !== $node->trait ? $this->p($node->trait) . '::' : '') . $node->method . ' as' . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') . (null !== $node->newName ? ' ' . $node->newName : '') . ';'; } protected function pStmt_Property(Stmt\Property $node) { return $this->pAttrGroups($node->attrGroups) . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) . ($node->type ? $this->p($node->type) . ' ' : '') . $this->pCommaSeparated($node->props) . ';'; } protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) { return '$' . $node->name . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } protected function pStmt_ClassMethod(Stmt\ClassMethod $node) { return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pMaybeMultiline($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . (null !== $node->stmts ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); } protected function pStmt_ClassConst(Stmt\ClassConst $node) { return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'const ' . $this->pCommaSeparated($node->consts) . ';'; } protected function pStmt_Function(Stmt\Function_ $node) { return $this->pAttrGroups($node->attrGroups) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Const(Stmt\Const_ $node) { return 'const ' . $this->pCommaSeparated($node->consts) . ';'; } protected function pStmt_Declare(Stmt\Declare_ $node) { return 'declare (' . $this->pCommaSeparated($node->declares) . ')' . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); } protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) { return $node->key . '=' . $this->p($node->value); } // Control flow protected function pStmt_If(Stmt\If_ $node) { return 'if (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '') . (null !== $node->else ? ' ' . $this->p($node->else) : ''); } protected function pStmt_ElseIf(Stmt\ElseIf_ $node) { return 'elseif (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Else(Stmt\Else_ $node) { return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_For(Stmt\For_ $node) { return 'for (' . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') . $this->pCommaSeparated($node->loop) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Foreach(Stmt\Foreach_ $node) { return 'foreach (' . $this->p($node->expr) . ' as ' . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_While(Stmt\While_ $node) { return 'while (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Do(Stmt\Do_ $node) { return 'do {' . $this->pStmts($node->stmts) . $this->nl . '} while (' . $this->p($node->cond) . ');'; } protected function pStmt_Switch(Stmt\Switch_ $node) { return 'switch (' . $this->p($node->cond) . ') {' . $this->pStmts($node->cases) . $this->nl . '}'; } protected function pStmt_Case(Stmt\Case_ $node) { return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' . $this->pStmts($node->stmts); } protected function pStmt_TryCatch(Stmt\TryCatch $node) { return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '') . ($node->finally !== null ? ' ' . $this->p($node->finally) : ''); } protected function pStmt_Catch(Stmt\Catch_ $node) { return 'catch (' . $this->pImplode($node->types, '|') . ($node->var !== null ? ' ' . $this->p($node->var) : '') . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Finally(Stmt\Finally_ $node) { return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Break(Stmt\Break_ $node) { return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } protected function pStmt_Continue(Stmt\Continue_ $node) { return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } protected function pStmt_Return(Stmt\Return_ $node) { return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; } protected function pStmt_Throw(Stmt\Throw_ $node) { return 'throw ' . $this->p($node->expr) . ';'; } protected function pStmt_Label(Stmt\Label $node) { return $node->name . ':'; } protected function pStmt_Goto(Stmt\Goto_ $node) { return 'goto ' . $node->name . ';'; } // Other protected function pStmt_Expression(Stmt\Expression $node) { return $this->p($node->expr) . ';'; } protected function pStmt_Echo(Stmt\Echo_ $node) { return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; } protected function pStmt_Static(Stmt\Static_ $node) { return 'static ' . $this->pCommaSeparated($node->vars) . ';'; } protected function pStmt_Global(Stmt\Global_ $node) { return 'global ' . $this->pCommaSeparated($node->vars) . ';'; } protected function pStmt_StaticVar(Stmt\StaticVar $node) { return $this->p($node->var) . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } protected function pStmt_Unset(Stmt\Unset_ $node) { return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; } protected function pStmt_InlineHTML(Stmt\InlineHTML $node) { $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : ''; return '?>' . $newline . $node->value . 'remaining; } protected function pStmt_Nop(Stmt\Nop $node) { return ''; } // Helpers protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) { return $this->pAttrGroups($node->attrGroups, $node->name === null) . $this->pModifiers($node->flags) . 'class' . $afterClassToken . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pObjectProperty($node) { if ($node instanceof Expr) { return '{' . $this->p($node) . '}'; } else { return $node; } } protected function pEncapsList(array $encapsList, $quote) { $return = ''; foreach ($encapsList as $element) { if ($element instanceof Scalar\EncapsedStringPart) { $return .= $this->escapeString($element->value, $quote); } else { $return .= '{' . $this->p($element) . '}'; } } return $return; } protected function pSingleQuotedString(string $string) { return '\'' . addcslashes($string, '\'\\') . '\''; } protected function escapeString($string, $quote) { if (null === $quote) { // For doc strings, don't escape newlines $escaped = addcslashes($string, "\t\f\v$\\"); } else { $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\"); } // Escape control characters and non-UTF-8 characters. // Regex based on https://stackoverflow.com/a/11709412/385378. $regex = '/( [\x00-\x08\x0E-\x1F] # Control characters | [\xC0-\xC1] # Invalid UTF-8 Bytes | [\xF5-\xFF] # Invalid UTF-8 Bytes | \xE0(?=[\x80-\x9F]) # Overlong encoding of prior code point | \xF0(?=[\x80-\x8F]) # Overlong encoding of prior code point | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle | (? $part) { $atStart = $i === 0; $atEnd = $i === count($parts) - 1; if ($part instanceof Scalar\EncapsedStringPart && $this->containsEndLabel($part->value, $label, $atStart, $atEnd) ) { return true; } } return false; } protected function pDereferenceLhs(Node $node) { if (!$this->dereferenceLhsRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } protected function pCallLhs(Node $node) { if (!$this->callLhsRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } protected function pNewVariable(Node $node) { // TODO: This is not fully accurate. return $this->pDereferenceLhs($node); } /** * @param Node[] $nodes * @return bool */ protected function hasNodeWithComments(array $nodes) { foreach ($nodes as $node) { if ($node && $node->getComments()) { return true; } } return false; } protected function pMaybeMultiline(array $nodes, bool $trailingComma = false) { if (!$this->hasNodeWithComments($nodes)) { return $this->pCommaSeparated($nodes); } else { return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl; } } protected function pAttrGroups(array $nodes, bool $inline = false): string { $result = ''; $sep = $inline ? ' ' : $this->nl; foreach ($nodes as $node) { $result .= $this->p($node) . $sep; } return $result; } } php-parser/lib/PhpParser/NameContext.php000064400000023303150250175720014242 0ustar00 [aliasName => originalName]] */ protected $aliases = []; /** @var Name[][] Same as $aliases but preserving original case */ protected $origAliases = []; /** @var ErrorHandler Error handler */ protected $errorHandler; /** * Create a name context. * * @param ErrorHandler $errorHandler Error handling used to report errors */ public function __construct(ErrorHandler $errorHandler) { $this->errorHandler = $errorHandler; } /** * Start a new namespace. * * This also resets the alias table. * * @param Name|null $namespace Null is the global namespace */ public function startNamespace(Name $namespace = null) { $this->namespace = $namespace; $this->origAliases = $this->aliases = [ Stmt\Use_::TYPE_NORMAL => [], Stmt\Use_::TYPE_FUNCTION => [], Stmt\Use_::TYPE_CONSTANT => [], ]; } /** * Add an alias / import. * * @param Name $name Original name * @param string $aliasName Aliased name * @param int $type One of Stmt\Use_::TYPE_* * @param array $errorAttrs Attributes to use to report an error */ public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []) { // Constant names are case sensitive, everything else case insensitive if ($type === Stmt\Use_::TYPE_CONSTANT) { $aliasLookupName = $aliasName; } else { $aliasLookupName = strtolower($aliasName); } if (isset($this->aliases[$type][$aliasLookupName])) { $typeStringMap = [ Stmt\Use_::TYPE_NORMAL => '', Stmt\Use_::TYPE_FUNCTION => 'function ', Stmt\Use_::TYPE_CONSTANT => 'const ', ]; $this->errorHandler->handleError(new Error( sprintf( 'Cannot use %s%s as %s because the name is already in use', $typeStringMap[$type], $name, $aliasName ), $errorAttrs )); return; } $this->aliases[$type][$aliasLookupName] = $name; $this->origAliases[$type][$aliasName] = $name; } /** * Get current namespace. * * @return null|Name Namespace (or null if global namespace) */ public function getNamespace() { return $this->namespace; } /** * Get resolved name. * * @param Name $name Name to resolve * @param int $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT} * * @return null|Name Resolved name, or null if static resolution is not possible */ public function getResolvedName(Name $name, int $type) { // don't resolve special class names if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) { if (!$name->isUnqualified()) { $this->errorHandler->handleError(new Error( sprintf("'\\%s' is an invalid class name", $name->toString()), $name->getAttributes() )); } return $name; } // fully qualified names are already resolved if ($name->isFullyQualified()) { return $name; } // Try to resolve aliases if (null !== $resolvedName = $this->resolveAlias($name, $type)) { return $resolvedName; } if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) { if (null === $this->namespace) { // outside of a namespace unaliased unqualified is same as fully qualified return new FullyQualified($name, $name->getAttributes()); } // Cannot resolve statically return null; } // if no alias exists prepend current namespace return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); } /** * Get resolved class name. * * @param Name $name Class ame to resolve * * @return Name Resolved name */ public function getResolvedClassName(Name $name) : Name { return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL); } /** * Get possible ways of writing a fully qualified name (e.g., by making use of aliases). * * @param string $name Fully-qualified name (without leading namespace separator) * @param int $type One of Stmt\Use_::TYPE_* * * @return Name[] Possible representations of the name */ public function getPossibleNames(string $name, int $type) : array { $lcName = strtolower($name); if ($type === Stmt\Use_::TYPE_NORMAL) { // self, parent and static must always be unqualified if ($lcName === "self" || $lcName === "parent" || $lcName === "static") { return [new Name($name)]; } } // Collect possible ways to write this name, starting with the fully-qualified name $possibleNames = [new FullyQualified($name)]; if (null !== $nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type)) { // Make sure there is no alias that makes the normally namespace-relative name // into something else if (null === $this->resolveAlias($nsRelativeName, $type)) { $possibleNames[] = $nsRelativeName; } } // Check for relevant namespace use statements foreach ($this->origAliases[Stmt\Use_::TYPE_NORMAL] as $alias => $orig) { $lcOrig = $orig->toLowerString(); if (0 === strpos($lcName, $lcOrig . '\\')) { $possibleNames[] = new Name($alias . substr($name, strlen($lcOrig))); } } // Check for relevant type-specific use statements foreach ($this->origAliases[$type] as $alias => $orig) { if ($type === Stmt\Use_::TYPE_CONSTANT) { // Constants are are complicated-sensitive $normalizedOrig = $this->normalizeConstName($orig->toString()); if ($normalizedOrig === $this->normalizeConstName($name)) { $possibleNames[] = new Name($alias); } } else { // Everything else is case-insensitive if ($orig->toLowerString() === $lcName) { $possibleNames[] = new Name($alias); } } } return $possibleNames; } /** * Get shortest representation of this fully-qualified name. * * @param string $name Fully-qualified name (without leading namespace separator) * @param int $type One of Stmt\Use_::TYPE_* * * @return Name Shortest representation */ public function getShortName(string $name, int $type) : Name { $possibleNames = $this->getPossibleNames($name, $type); // Find shortest name $shortestName = null; $shortestLength = \INF; foreach ($possibleNames as $possibleName) { $length = strlen($possibleName->toCodeString()); if ($length < $shortestLength) { $shortestName = $possibleName; $shortestLength = $length; } } return $shortestName; } private function resolveAlias(Name $name, $type) { $firstPart = $name->getFirst(); if ($name->isQualified()) { // resolve aliases for qualified names, always against class alias table $checkName = strtolower($firstPart); if (isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName])) { $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName]; return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); } } elseif ($name->isUnqualified()) { // constant aliases are case-sensitive, function aliases case-insensitive $checkName = $type === Stmt\Use_::TYPE_CONSTANT ? $firstPart : strtolower($firstPart); if (isset($this->aliases[$type][$checkName])) { // resolve unqualified aliases return new FullyQualified($this->aliases[$type][$checkName], $name->getAttributes()); } } // No applicable aliases return null; } private function getNamespaceRelativeName(string $name, string $lcName, int $type) { if (null === $this->namespace) { return new Name($name); } if ($type === Stmt\Use_::TYPE_CONSTANT) { // The constants true/false/null always resolve to the global symbols, even inside a // namespace, so they may be used without qualification if ($lcName === "true" || $lcName === "false" || $lcName === "null") { return new Name($name); } } $namespacePrefix = strtolower($this->namespace . '\\'); if (0 === strpos($lcName, $namespacePrefix)) { return new Name(substr($name, strlen($namespacePrefix))); } return null; } private function normalizeConstName(string $name) { $nsSep = strrpos($name, '\\'); if (false === $nsSep) { return $name; } // Constants have case-insensitive namespace and case-sensitive short-name $ns = substr($name, 0, $nsSep); $shortName = substr($name, $nsSep + 1); return strtolower($ns) . '\\' . $shortName; } } php-parser/lib/PhpParser/Node/MatchArm.php000064400000001215150250175720014374 0ustar00conds = $conds; $this->body = $body; $this->attributes = $attributes; } public function getSubNodeNames() : array { return ['conds', 'body']; } public function getType() : string { return 'MatchArm'; } } php-parser/lib/PhpParser/Node/Param.php000064400000004165150250175720013747 0ustar00attributes = $attributes; $this->type = \is_string($type) ? new Identifier($type) : $type; $this->byRef = $byRef; $this->variadic = $variadic; $this->var = $var; $this->default = $default; $this->flags = $flags; $this->attrGroups = $attrGroups; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } public function getType() : string { return 'Param'; } } php-parser/lib/PhpParser/Node/Attribute.php000064400000001450150250175720014644 0ustar00attributes = $attributes; $this->name = $name; $this->args = $args; } public function getSubNodeNames() : array { return ['name', 'args']; } public function getType() : string { return 'Attribute'; } } php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php000064400000000475150250175720017032 0ustar00attributes = $attributes; } public function getSubNodeNames() : array { return []; } /** * Get name of magic constant. * * @return string Name of magic constant */ abstract public function getName() : string; } php-parser/lib/PhpParser/Node/Scalar/LNumber.php000064400000004617150250175720015462 0ustar00attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } /** * Constructs an LNumber node from a string number literal. * * @param string $str String number literal (decimal, octal, hex or binary) * @param array $attributes Additional attributes * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5) * * @return LNumber The constructed LNumber, including kind attribute */ public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber { $attributes['rawValue'] = $str; $str = str_replace('_', '', $str); if ('0' !== $str[0] || '0' === $str) { $attributes['kind'] = LNumber::KIND_DEC; return new LNumber((int) $str, $attributes); } if ('x' === $str[1] || 'X' === $str[1]) { $attributes['kind'] = LNumber::KIND_HEX; return new LNumber(hexdec($str), $attributes); } if ('b' === $str[1] || 'B' === $str[1]) { $attributes['kind'] = LNumber::KIND_BIN; return new LNumber(bindec($str), $attributes); } if (!$allowInvalidOctal && strpbrk($str, '89')) { throw new Error('Invalid numeric literal', $attributes); } // Strip optional explicit octal prefix. if ('o' === $str[1] || 'O' === $str[1]) { $str = substr($str, 2); } // use intval instead of octdec to get proper cutting behavior with malformed numbers $attributes['kind'] = LNumber::KIND_OCT; return new LNumber(intval($str, 8), $attributes); } public function getType() : string { return 'Scalar_LNumber'; } } php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php000064400000001321150250175720017643 0ustar00attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } public function getType() : string { return 'Scalar_EncapsedStringPart'; } } php-parser/lib/PhpParser/Node/Scalar/Encapsed.php000064400000001274150250175720015634 0ustar00attributes = $attributes; $this->parts = $parts; } public function getSubNodeNames() : array { return ['parts']; } public function getType() : string { return 'Scalar_Encapsed'; } } php-parser/lib/PhpParser/Node/Scalar/DNumber.php000064400000003741150250175720015447 0ustar00attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } /** * @param mixed[] $attributes */ public static function fromString(string $str, array $attributes = []): DNumber { $attributes['rawValue'] = $str; $float = self::parse($str); return new DNumber($float, $attributes); } /** * @internal * * Parses a DNUMBER token like PHP would. * * @param string $str A string number * * @return float The parsed number */ public static function parse(string $str) : float { $str = str_replace('_', '', $str); // Check whether this is one of the special integer notations. if ('0' === $str[0]) { // hex if ('x' === $str[1] || 'X' === $str[1]) { return hexdec($str); } // bin if ('b' === $str[1] || 'B' === $str[1]) { return bindec($str); } // oct, but only if the string does not contain any of '.eE'. if (false === strpbrk($str, '.eE')) { // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit // (8 or 9) so that only the digits before that are used. return octdec(substr($str, 0, strcspn($str, '89'))); } } // dec return (float) $str; } public function getType() : string { return 'Scalar_DNumber'; } } php-parser/lib/PhpParser/Node/Scalar/String_.php000064400000011125150250175720015513 0ustar00 '\\', '$' => '$', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1B", ]; /** * Constructs a string scalar node. * * @param string $value Value of the string * @param array $attributes Additional attributes */ public function __construct(string $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } /** * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes */ public static function fromString(string $str, array $attributes = [], bool $parseUnicodeEscape = true): self { $attributes['kind'] = ($str[0] === "'" || ($str[1] === "'" && ($str[0] === 'b' || $str[0] === 'B'))) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED; $attributes['rawValue'] = $str; $string = self::parse($str, $parseUnicodeEscape); return new self($string, $attributes); } /** * @internal * * Parses a string token. * * @param string $str String token content * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes * * @return string The parsed string */ public static function parse(string $str, bool $parseUnicodeEscape = true) : string { $bLength = 0; if ('b' === $str[0] || 'B' === $str[0]) { $bLength = 1; } if ('\'' === $str[$bLength]) { return str_replace( ['\\\\', '\\\''], ['\\', '\''], substr($str, $bLength + 1, -1) ); } else { return self::parseEscapeSequences( substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape ); } } /** * @internal * * Parses escape sequences in strings (all string types apart from single quoted). * * @param string $str String without quotes * @param null|string $quote Quote type * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes * * @return string String with escape sequences parsed */ public static function parseEscapeSequences(string $str, $quote, bool $parseUnicodeEscape = true) : string { if (null !== $quote) { $str = str_replace('\\' . $quote, $quote, $str); } $extra = ''; if ($parseUnicodeEscape) { $extra = '|u\{([0-9a-fA-F]+)\}'; } return preg_replace_callback( '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', function($matches) { $str = $matches[1]; if (isset(self::$replacements[$str])) { return self::$replacements[$str]; } elseif ('x' === $str[0] || 'X' === $str[0]) { return chr(hexdec(substr($str, 1))); } elseif ('u' === $str[0]) { return self::codePointToUtf8(hexdec($matches[2])); } else { return chr(octdec($str)); } }, $str ); } /** * Converts a Unicode code point to its UTF-8 encoded representation. * * @param int $num Code point * * @return string UTF-8 representation of code point */ private static function codePointToUtf8(int $num) : string { if ($num <= 0x7F) { return chr($num); } if ($num <= 0x7FF) { return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80); } if ($num <= 0xFFFF) { return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); } if ($num <= 0x1FFFFF) { return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); } throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large'); } public function getType() : string { return 'Scalar_String'; } } php-parser/lib/PhpParser/Node/AttributeGroup.php000064400000001210150250175720015653 0ustar00attributes = $attributes; $this->attrs = $attrs; } public function getSubNodeNames() : array { return ['attrs']; } public function getType() : string { return 'AttributeGroup'; } } php-parser/lib/PhpParser/Node/ComplexType.php000064400000000503150250175720015150 0ustar00attributes = $attributes; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['stmts']; } public function getType() : string { return 'Stmt_Finally'; } } php-parser/lib/PhpParser/Node/Stmt/Static_.php000064400000001260150250175720015215 0ustar00attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Stmt_Static'; } } php-parser/lib/PhpParser/Node/Stmt/Function_.php000064400000004774150250175720015570 0ustar00 false : Whether to return by reference * 'params' => array(): Parameters * 'returnType' => null : Return type * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->byRef = $subNodes['byRef'] ?? false; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->params = $subNodes['params'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getAttrGroups() : array { return $this->attrGroups; } /** @return Node\Stmt[] */ public function getStmts() : array { return $this->stmts; } public function getType() : string { return 'Stmt_Function'; } } php-parser/lib/PhpParser/Node/Stmt/EnumCase.php000064400000002222150250175720015326 0ustar00name = \is_string($name) ? new Node\Identifier($name) : $name; $this->expr = $expr; $this->attrGroups = $attrGroups; } public function getSubNodeNames() : array { return ['attrGroups', 'name', 'expr']; } public function getType() : string { return 'Stmt_EnumCase'; } } php-parser/lib/PhpParser/Node/Stmt/Break_.php000064400000001265150250175720015017 0ustar00attributes = $attributes; $this->num = $num; } public function getSubNodeNames() : array { return ['num']; } public function getType() : string { return 'Stmt_Break'; } } php-parser/lib/PhpParser/Node/Stmt/Trait_.php000064400000001751150250175720015056 0ustar00 array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'name', 'stmts']; } public function getType() : string { return 'Stmt_Trait'; } } php-parser/lib/PhpParser/Node/Stmt/Return_.php000064400000001241150250175720015244 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Stmt_Return'; } } php-parser/lib/PhpParser/Node/Stmt/Global_.php000064400000001243150250175720015167 0ustar00attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Stmt_Global'; } } php-parser/lib/PhpParser/Node/Stmt/UseUse.php000064400000003105150250175720015040 0ustar00attributes = $attributes; $this->type = $type; $this->name = $name; $this->alias = \is_string($alias) ? new Identifier($alias) : $alias; } public function getSubNodeNames() : array { return ['type', 'name', 'alias']; } /** * Get alias. If not explicitly given this is the last component of the used name. * * @return Identifier */ public function getAlias() : Identifier { if (null !== $this->alias) { return $this->alias; } return new Identifier($this->name->getLast()); } public function getType() : string { return 'Stmt_UseUse'; } } php-parser/lib/PhpParser/Node/Stmt/StaticVar.php000064400000001610150250175720015526 0ustar00attributes = $attributes; $this->var = $var; $this->default = $default; } public function getSubNodeNames() : array { return ['var', 'default']; } public function getType() : string { return 'Stmt_StaticVar'; } } php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php000064400000001362150250175720016215 0ustar00attributes = $attributes; $this->remaining = $remaining; } public function getSubNodeNames() : array { return ['remaining']; } public function getType() : string { return 'Stmt_HaltCompiler'; } } php-parser/lib/PhpParser/Node/Stmt/Label.php000064400000001315150250175720014647 0ustar00attributes = $attributes; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Stmt_Label'; } } php-parser/lib/PhpParser/Node/Stmt/Namespace_.php000064400000001653150250175720015670 0ustar00attributes = $attributes; $this->name = $name; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['name', 'stmts']; } public function getType() : string { return 'Stmt_Namespace'; } } php-parser/lib/PhpParser/Node/Stmt/Case_.php000064400000001527150250175720014647 0ustar00attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; } public function getType() : string { return 'Stmt_Case'; } } php-parser/lib/PhpParser/Node/Stmt/Throw_.php000064400000001231150250175720015067 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Stmt_Throw'; } } php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php000064400000001710150250175720017220 0ustar00attributes = $attributes; $this->name = \is_string($name) ? new Node\VarLikeIdentifier($name) : $name; $this->default = $default; } public function getSubNodeNames() : array { return ['name', 'default']; } public function getType() : string { return 'Stmt_PropertyProperty'; } } php-parser/lib/PhpParser/Node/Stmt/Enum_.php000064400000003045150250175720014675 0ustar00 null : Scalar type * 'implements' => array() : Names of implemented interfaces * 'stmts' => array() : Statements * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->scalarType = $subNodes['scalarType'] ?? null; $this->implements = $subNodes['implements'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; parent::__construct($attributes); } public function getSubNodeNames() : array { return ['attrGroups', 'name', 'scalarType', 'implements', 'stmts']; } public function getType() : string { return 'Stmt_Enum'; } } php-parser/lib/PhpParser/Node/Stmt/Echo_.php000064400000001217150250175720014646 0ustar00attributes = $attributes; $this->exprs = $exprs; } public function getSubNodeNames() : array { return ['exprs']; } public function getType() : string { return 'Stmt_Echo'; } } php-parser/lib/PhpParser/Node/Stmt/Continue_.php000064400000001304150250175720015551 0ustar00attributes = $attributes; $this->num = $num; } public function getSubNodeNames() : array { return ['num']; } public function getType() : string { return 'Stmt_Continue'; } } php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php000064400000002454150250175720020433 0ustar00attributes = $attributes; $this->trait = $trait; $this->method = \is_string($method) ? new Node\Identifier($method) : $method; $this->newModifier = $newModifier; $this->newName = \is_string($newName) ? new Node\Identifier($newName) : $newName; } public function getSubNodeNames() : array { return ['trait', 'method', 'newModifier', 'newName']; } public function getType() : string { return 'Stmt_TraitUseAdaptation_Alias'; } } php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php000064400000002105150250175720021430 0ustar00attributes = $attributes; $this->trait = $trait; $this->method = \is_string($method) ? new Node\Identifier($method) : $method; $this->insteadof = $insteadof; } public function getSubNodeNames() : array { return ['trait', 'method', 'insteadof']; } public function getType() : string { return 'Stmt_TraitUseAdaptation_Precedence'; } } php-parser/lib/PhpParser/Node/Stmt/TraitUse.php000064400000001602150250175720015367 0ustar00attributes = $attributes; $this->traits = $traits; $this->adaptations = $adaptations; } public function getSubNodeNames() : array { return ['traits', 'adaptations']; } public function getType() : string { return 'Stmt_TraitUse'; } } php-parser/lib/PhpParser/Node/Stmt/Foreach_.php000064400000003131150250175720015334 0ustar00 null : Variable to assign key to * 'byRef' => false : Whether to assign value by reference * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; $this->keyVar = $subNodes['keyVar'] ?? null; $this->byRef = $subNodes['byRef'] ?? false; $this->valueVar = $valueVar; $this->stmts = $subNodes['stmts'] ?? []; } public function getSubNodeNames() : array { return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts']; } public function getType() : string { return 'Stmt_Foreach'; } } php-parser/lib/PhpParser/Node/Stmt/GroupUse.php000064400000001755150250175720015411 0ustar00attributes = $attributes; $this->type = $type; $this->prefix = $prefix; $this->uses = $uses; } public function getSubNodeNames() : array { return ['type', 'prefix', 'uses']; } public function getType() : string { return 'Stmt_GroupUse'; } } php-parser/lib/PhpParser/Node/Stmt/Else_.php000064400000001222150250175720014654 0ustar00attributes = $attributes; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['stmts']; } public function getType() : string { return 'Stmt_Else'; } } php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php000064400000000412150250175720017372 0ustar00 array(): Init expressions * 'cond' => array(): Loop conditions * 'loop' => array(): Loop expressions * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->init = $subNodes['init'] ?? []; $this->cond = $subNodes['cond'] ?? []; $this->loop = $subNodes['loop'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; } public function getSubNodeNames() : array { return ['init', 'cond', 'loop', 'stmts']; } public function getType() : string { return 'Stmt_For'; } } php-parser/lib/PhpParser/Node/Stmt/Class_.php000064400000010532150250175720015035 0ustar00 0 : Flags * 'extends' => null : Name of extended class * 'implements' => array(): Names of implemented interfaces * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->extends = $subNodes['extends'] ?? null; $this->implements = $subNodes['implements'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts']; } /** * Whether the class is explicitly abstract. * * @return bool */ public function isAbstract() : bool { return (bool) ($this->flags & self::MODIFIER_ABSTRACT); } /** * Whether the class is final. * * @return bool */ public function isFinal() : bool { return (bool) ($this->flags & self::MODIFIER_FINAL); } public function isReadonly() : bool { return (bool) ($this->flags & self::MODIFIER_READONLY); } /** * Whether the class is anonymous. * * @return bool */ public function isAnonymous() : bool { return null === $this->name; } /** * @internal */ public static function verifyClassModifier($a, $b) { if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { throw new Error('Multiple abstract modifiers are not allowed'); } if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { throw new Error('Multiple final modifiers are not allowed'); } if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { throw new Error('Multiple readonly modifiers are not allowed'); } if ($a & 48 && $b & 48) { throw new Error('Cannot use the final modifier on an abstract class'); } } /** * @internal */ public static function verifyModifier($a, $b) { if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) { throw new Error('Multiple access type modifiers are not allowed'); } if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { throw new Error('Multiple abstract modifiers are not allowed'); } if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) { throw new Error('Multiple static modifiers are not allowed'); } if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { throw new Error('Multiple final modifiers are not allowed'); } if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { throw new Error('Multiple readonly modifiers are not allowed'); } if ($a & 48 && $b & 48) { throw new Error('Cannot use the final modifier on an abstract class member'); } } public function getType() : string { return 'Stmt_Class'; } } php-parser/lib/PhpParser/Node/Stmt/ClassLike.php000064400000005572150250175720015513 0ustar00stmts as $stmt) { if ($stmt instanceof TraitUse) { $traitUses[] = $stmt; } } return $traitUses; } /** * @return ClassConst[] */ public function getConstants() : array { $constants = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof ClassConst) { $constants[] = $stmt; } } return $constants; } /** * @return Property[] */ public function getProperties() : array { $properties = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof Property) { $properties[] = $stmt; } } return $properties; } /** * Gets property with the given name defined directly in this class/interface/trait. * * @param string $name Name of the property * * @return Property|null Property node or null if the property does not exist */ public function getProperty(string $name) { foreach ($this->stmts as $stmt) { if ($stmt instanceof Property) { foreach ($stmt->props as $prop) { if ($prop instanceof PropertyProperty && $name === $prop->name->toString()) { return $stmt; } } } } return null; } /** * Gets all methods defined directly in this class/interface/trait * * @return ClassMethod[] */ public function getMethods() : array { $methods = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof ClassMethod) { $methods[] = $stmt; } } return $methods; } /** * Gets method with the given name defined directly in this class/interface/trait. * * @param string $name Name of the method (compared case-insensitively) * * @return ClassMethod|null Method node or null if the method does not exist */ public function getMethod(string $name) { $lowerName = strtolower($name); foreach ($this->stmts as $stmt) { if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) { return $stmt; } } return null; } } php-parser/lib/PhpParser/Node/Stmt/While_.php000064400000001460150250175720015040 0ustar00attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; } public function getType() : string { return 'Stmt_While'; } } php-parser/lib/PhpParser/Node/Stmt/Property.php000064400000005033150250175720015455 0ustar00attributes = $attributes; $this->flags = $flags; $this->props = $props; $this->type = \is_string($type) ? new Identifier($type) : $type; $this->attrGroups = $attrGroups; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'props']; } /** * Whether the property is explicitly or implicitly public. * * @return bool */ public function isPublic() : bool { return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; } /** * Whether the property is protected. * * @return bool */ public function isProtected() : bool { return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); } /** * Whether the property is private. * * @return bool */ public function isPrivate() : bool { return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); } /** * Whether the property is static. * * @return bool */ public function isStatic() : bool { return (bool) ($this->flags & Class_::MODIFIER_STATIC); } /** * Whether the property is readonly. * * @return bool */ public function isReadonly() : bool { return (bool) ($this->flags & Class_::MODIFIER_READONLY); } public function getType() : string { return 'Stmt_Property'; } } php-parser/lib/PhpParser/Node/Stmt/Catch_.php000064400000002151150250175720015010 0ustar00attributes = $attributes; $this->types = $types; $this->var = $var; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['types', 'var', 'stmts']; } public function getType() : string { return 'Stmt_Catch'; } } php-parser/lib/PhpParser/Node/Stmt/Do_.php000064400000001455150250175720014336 0ustar00attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['stmts', 'cond']; } public function getType() : string { return 'Stmt_Do'; } } php-parser/lib/PhpParser/Node/Stmt/Interface_.php000064400000002315150250175720015670 0ustar00 array(): Name of extended interfaces * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->extends = $subNodes['extends'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'name', 'extends', 'stmts']; } public function getType() : string { return 'Stmt_Interface'; } } php-parser/lib/PhpParser/Node/Stmt/Use_.php000064400000002530150250175720014523 0ustar00attributes = $attributes; $this->type = $type; $this->uses = $uses; } public function getSubNodeNames() : array { return ['type', 'uses']; } public function getType() : string { return 'Stmt_Use'; } } php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php000064400000001601150250175720016445 0ustar00value pair node. * * @param string|Node\Identifier $key Key * @param Node\Expr $value Value * @param array $attributes Additional attributes */ public function __construct($key, Node\Expr $value, array $attributes = []) { $this->attributes = $attributes; $this->key = \is_string($key) ? new Node\Identifier($key) : $key; $this->value = $value; } public function getSubNodeNames() : array { return ['key', 'value']; } public function getType() : string { return 'Stmt_DeclareDeclare'; } } php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php000064400000001464150250175720015143 0ustar00attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; } public function getType() : string { return 'Stmt_ElseIf'; } } php-parser/lib/PhpParser/Node/Stmt/Goto_.php000064400000001363150250175720014702 0ustar00attributes = $attributes; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Stmt_Goto'; } } php-parser/lib/PhpParser/Node/Stmt/Unset_.php000064400000001233150250175720015064 0ustar00attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Stmt_Unset'; } } php-parser/lib/PhpParser/Node/Stmt/ClassConst.php000064400000003707150250175720015713 0ustar00attributes = $attributes; $this->flags = $flags; $this->consts = $consts; $this->attrGroups = $attrGroups; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'consts']; } /** * Whether constant is explicitly or implicitly public. * * @return bool */ public function isPublic() : bool { return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; } /** * Whether constant is protected. * * @return bool */ public function isProtected() : bool { return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); } /** * Whether constant is private. * * @return bool */ public function isPrivate() : bool { return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); } /** * Whether constant is final. * * @return bool */ public function isFinal() : bool { return (bool) ($this->flags & Class_::MODIFIER_FINAL); } public function getType() : string { return 'Stmt_ClassConst'; } } php-parser/lib/PhpParser/Node/Stmt/Switch_.php000064400000001440150250175720015227 0ustar00attributes = $attributes; $this->cond = $cond; $this->cases = $cases; } public function getSubNodeNames() : array { return ['cond', 'cases']; } public function getType() : string { return 'Stmt_Switch'; } } php-parser/lib/PhpParser/Node/Stmt/If_.php000064400000002445150250175720014332 0ustar00 array(): Statements * 'elseifs' => array(): Elseif clauses * 'else' => null : Else clause * @param array $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $subNodes['stmts'] ?? []; $this->elseifs = $subNodes['elseifs'] ?? []; $this->else = $subNodes['else'] ?? null; } public function getSubNodeNames() : array { return ['cond', 'stmts', 'elseifs', 'else']; } public function getType() : string { return 'Stmt_If'; } } php-parser/lib/PhpParser/Node/Stmt/Const_.php000064400000001265150250175720015061 0ustar00attributes = $attributes; $this->consts = $consts; } public function getSubNodeNames() : array { return ['consts']; } public function getType() : string { return 'Stmt_Const'; } } php-parser/lib/PhpParser/Node/Stmt/Nop.php000064400000000455150250175720014370 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Stmt_Expression'; } } php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php000064400000001211150250175720015526 0ustar00attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } public function getType() : string { return 'Stmt_InlineHTML'; } } php-parser/lib/PhpParser/Node/Stmt/Declare_.php000064400000001561150250175720015331 0ustar00attributes = $attributes; $this->declares = $declares; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['declares', 'stmts']; } public function getType() : string { return 'Stmt_Declare'; } } php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php000064400000011211150250175720016032 0ustar00 true, '__destruct' => true, '__call' => true, '__callstatic' => true, '__get' => true, '__set' => true, '__isset' => true, '__unset' => true, '__sleep' => true, '__wakeup' => true, '__tostring' => true, '__set_state' => true, '__clone' => true, '__invoke' => true, '__debuginfo' => true, '__serialize' => true, '__unserialize' => true, ]; /** * Constructs a class method node. * * @param string|Node\Identifier $name Name * @param array $subNodes Array of the following optional subnodes: * 'flags => MODIFIER_PUBLIC: Flags * 'byRef' => false : Whether to return by reference * 'params' => array() : Parameters * 'returnType' => null : Return type * 'stmts' => array() : Statements * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->byRef = $subNodes['byRef'] ?? false; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->params = $subNodes['params'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getStmts() { return $this->stmts; } public function getAttrGroups() : array { return $this->attrGroups; } /** * Whether the method is explicitly or implicitly public. * * @return bool */ public function isPublic() : bool { return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; } /** * Whether the method is protected. * * @return bool */ public function isProtected() : bool { return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); } /** * Whether the method is private. * * @return bool */ public function isPrivate() : bool { return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); } /** * Whether the method is abstract. * * @return bool */ public function isAbstract() : bool { return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT); } /** * Whether the method is final. * * @return bool */ public function isFinal() : bool { return (bool) ($this->flags & Class_::MODIFIER_FINAL); } /** * Whether the method is static. * * @return bool */ public function isStatic() : bool { return (bool) ($this->flags & Class_::MODIFIER_STATIC); } /** * Whether the method is magic. * * @return bool */ public function isMagic() : bool { return isset(self::$magicNames[$this->name->toLowerString()]); } public function getType() : string { return 'Stmt_ClassMethod'; } } php-parser/lib/PhpParser/Node/Stmt/TryCatch.php000064400000002013150250175720015345 0ustar00attributes = $attributes; $this->stmts = $stmts; $this->catches = $catches; $this->finally = $finally; } public function getSubNodeNames() : array { return ['stmts', 'catches', 'finally']; } public function getType() : string { return 'Stmt_TryCatch'; } } php-parser/lib/PhpParser/Node/Name/FullyQualified.php000064400000002234150250175720016501 0ustar00toString(); } public function getType() : string { return 'Name_FullyQualified'; } } php-parser/lib/PhpParser/Node/Name/Relative.php000064400000002231150250175720015332 0ustar00toString(); } public function getType() : string { return 'Name_Relative'; } } php-parser/lib/PhpParser/Node/VarLikeIdentifier.php000064400000000767150250175720016253 0ustar00attributes = $attributes; $this->type = \is_string($type) ? new Identifier($type) : $type; } public function getSubNodeNames() : array { return ['type']; } public function getType() : string { return 'NullableType'; } } php-parser/lib/PhpParser/Node/Stmt.php000064400000000205150250175720013625 0ustar00 true, 'parent' => true, 'static' => true, ]; /** * Constructs a name node. * * @param string|string[]|self $name Name as string, part array or Name instance (copy ctor) * @param array $attributes Additional attributes */ public function __construct($name, array $attributes = []) { $this->attributes = $attributes; $this->parts = self::prepareName($name); } public function getSubNodeNames() : array { return ['parts']; } /** * Gets the first part of the name, i.e. everything before the first namespace separator. * * @return string First part of the name */ public function getFirst() : string { return $this->parts[0]; } /** * Gets the last part of the name, i.e. everything after the last namespace separator. * * @return string Last part of the name */ public function getLast() : string { return $this->parts[count($this->parts) - 1]; } /** * Checks whether the name is unqualified. (E.g. Name) * * @return bool Whether the name is unqualified */ public function isUnqualified() : bool { return 1 === count($this->parts); } /** * Checks whether the name is qualified. (E.g. Name\Name) * * @return bool Whether the name is qualified */ public function isQualified() : bool { return 1 < count($this->parts); } /** * Checks whether the name is fully qualified. (E.g. \Name) * * @return bool Whether the name is fully qualified */ public function isFullyQualified() : bool { return false; } /** * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) * * @return bool Whether the name is relative */ public function isRelative() : bool { return false; } /** * Returns a string representation of the name itself, without taking the name type into * account (e.g., not including a leading backslash for fully qualified names). * * @return string String representation */ public function toString() : string { return implode('\\', $this->parts); } /** * Returns a string representation of the name as it would occur in code (e.g., including * leading backslash for fully qualified names. * * @return string String representation */ public function toCodeString() : string { return $this->toString(); } /** * Returns lowercased string representation of the name, without taking the name type into * account (e.g., no leading backslash for fully qualified names). * * @return string Lowercased string representation */ public function toLowerString() : string { return strtolower(implode('\\', $this->parts)); } /** * Checks whether the identifier is a special class name (self, parent or static). * * @return bool Whether identifier is a special class name */ public function isSpecialClassName() : bool { return count($this->parts) === 1 && isset(self::$specialClassNames[strtolower($this->parts[0])]); } /** * Returns a string representation of the name by imploding the namespace parts with the * namespace separator. * * @return string String representation */ public function __toString() : string { return implode('\\', $this->parts); } /** * Gets a slice of a name (similar to array_slice). * * This method returns a new instance of the same type as the original and with the same * attributes. * * If the slice is empty, null is returned. The null value will be correctly handled in * concatenations using concat(). * * Offset and length have the same meaning as in array_slice(). * * @param int $offset Offset to start the slice at (may be negative) * @param int|null $length Length of the slice (may be negative) * * @return static|null Sliced name */ public function slice(int $offset, int $length = null) { $numParts = count($this->parts); $realOffset = $offset < 0 ? $offset + $numParts : $offset; if ($realOffset < 0 || $realOffset > $numParts) { throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset)); } if (null === $length) { $realLength = $numParts - $realOffset; } else { $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; if ($realLength < 0 || $realLength > $numParts - $realOffset) { throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length)); } } if ($realLength === 0) { // Empty slice is represented as null return null; } return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes); } /** * Concatenate two names, yielding a new Name instance. * * The type of the generated instance depends on which class this method is called on, for * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. * * If one of the arguments is null, a new instance of the other name will be returned. If both * arguments are null, null will be returned. As such, writing * Name::concat($namespace, $shortName) * where $namespace is a Name node or null will work as expected. * * @param string|string[]|self|null $name1 The first name * @param string|string[]|self|null $name2 The second name * @param array $attributes Attributes to assign to concatenated name * * @return static|null Concatenated name */ public static function concat($name1, $name2, array $attributes = []) { if (null === $name1 && null === $name2) { return null; } elseif (null === $name1) { return new static(self::prepareName($name2), $attributes); } elseif (null === $name2) { return new static(self::prepareName($name1), $attributes); } else { return new static( array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes ); } } /** * Prepares a (string, array or Name node) name for use in name changing methods by converting * it to an array. * * @param string|string[]|self $name Name to prepare * * @return string[] Prepared name */ private static function prepareName($name) : array { if (\is_string($name)) { if ('' === $name) { throw new \InvalidArgumentException('Name cannot be empty'); } return explode('\\', $name); } elseif (\is_array($name)) { if (empty($name)) { throw new \InvalidArgumentException('Name cannot be empty'); } return $name; } elseif ($name instanceof self) { return $name->parts; } throw new \InvalidArgumentException( 'Expected string, array of parts or Name instance' ); } public function getType() : string { return 'Name'; } } php-parser/lib/PhpParser/Node/UnionType.php000064400000001251150250175720014632 0ustar00attributes = $attributes; $this->types = $types; } public function getSubNodeNames() : array { return ['types']; } public function getType() : string { return 'UnionType'; } } php-parser/lib/PhpParser/Node/Expr.php000064400000000205150250175720013614 0ustar00attributes = $attributes; $this->name = $name; $this->value = $value; $this->byRef = $byRef; $this->unpack = $unpack; } public function getSubNodeNames() : array { return ['name', 'value', 'byRef', 'unpack']; } public function getType() : string { return 'Arg'; } } php-parser/lib/PhpParser/Node/VariadicPlaceholder.php000064400000001175150250175720016572 0ustar00attributes = $attributes; } public function getType(): string { return 'VariadicPlaceholder'; } public function getSubNodeNames(): array { return []; } }php-parser/lib/PhpParser/Node/Identifier.php000064400000003351150250175720014765 0ustar00 true, 'parent' => true, 'static' => true, ]; /** * Constructs an identifier node. * * @param string $name Identifier as string * @param array $attributes Additional attributes */ public function __construct(string $name, array $attributes = []) { $this->attributes = $attributes; $this->name = $name; } public function getSubNodeNames() : array { return ['name']; } /** * Get identifier as string. * * @return string Identifier as string. */ public function toString() : string { return $this->name; } /** * Get lowercased identifier as string. * * @return string Lowercased identifier as string */ public function toLowerString() : string { return strtolower($this->name); } /** * Checks whether the identifier is a special class name (self, parent or static). * * @return bool Whether identifier is a special class name */ public function isSpecialClassName() : bool { return isset(self::$specialClassNames[strtolower($this->name)]); } /** * Get identifier as string. * * @return string Identifier as string */ public function __toString() : string { return $this->name; } public function getType() : string { return 'Identifier'; } } php-parser/lib/PhpParser/Node/IntersectionType.php000064400000001266150250175720016216 0ustar00attributes = $attributes; $this->types = $types; } public function getSubNodeNames() : array { return ['types']; } public function getType() : string { return 'IntersectionType'; } } php-parser/lib/PhpParser/Node/Const_.php000064400000001714150250175720014131 0ustar00attributes = $attributes; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->value = $value; } public function getSubNodeNames() : array { return ['name', 'value']; } public function getType() : string { return 'Const'; } } php-parser/lib/PhpParser/Node/Expr/AssignRef.php000064400000001463150250175720015504 0ustar00attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames() : array { return ['var', 'expr']; } public function getType() : string { return 'Expr_AssignRef'; } } php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php000064400000000503150250175720017715 0ustar00>'; } public function getType() : string { return 'Expr_BinaryOp_ShiftRight'; } } php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php000064400000000506150250175720020233 0ustar00'; } public function getType() : string { return 'Expr_BinaryOp_Spaceship'; } } php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php000064400000000472150250175720017063 0ustar00'; } public function getType() : string { return 'Expr_BinaryOp_Greater'; } } php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php000064400000000474150250175720017222 0ustar00='; } public function getType() : string { return 'Expr_BinaryOp_GreaterOrEqual'; } } php-parser/lib/PhpParser/Node/Expr/PreDec.php000064400000001162150250175720014761 0ustar00attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PreDec'; } } php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php000064400000000321150250175720015537 0ustar00attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames() : array { return ['var', 'name']; } public function getType() : string { return 'Expr_PropertyFetch'; } } php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php000064400000001205150250175720015727 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_UnaryMinus'; } } php-parser/lib/PhpParser/Node/Expr/PostInc.php000064400000001171150250175720015176 0ustar00attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PostInc'; } } php-parser/lib/PhpParser/Node/Expr/FuncCall.php000064400000002022150250175720015302 0ustar00 Arguments */ public $args; /** * Constructs a function call node. * * @param Node\Name|Expr $name Function name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct($name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->name = $name; $this->args = $args; } public function getSubNodeNames() : array { return ['name', 'args']; } public function getType() : string { return 'Expr_FuncCall'; } public function getRawArgs(): array { return $this->args; } } php-parser/lib/PhpParser/Node/Expr/StaticCall.php000064400000002454150250175720015647 0ustar00 Arguments */ public $args; /** * Constructs a static method call node. * * @param Node\Name|Expr $class Class name * @param string|Identifier|Expr $name Method name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct($class, $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames() : array { return ['class', 'name', 'args']; } public function getType() : string { return 'Expr_StaticCall'; } public function getRawArgs(): array { return $this->args; } } php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php000064400000002465150250175720017334 0ustar00 Arguments */ public $args; /** * Constructs a nullsafe method call node. * * @param Expr $var Variable holding object * @param string|Identifier|Expr $name Method name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames() : array { return ['var', 'name', 'args']; } public function getType() : string { return 'Expr_NullsafeMethodCall'; } public function getRawArgs(): array { return $this->args; } } php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php000064400000001470150250175720016303 0ustar00attributes = $attributes; $this->var = $var; $this->dim = $dim; } public function getSubNodeNames() : array { return ['var', 'dim']; } public function getType() : string { return 'Expr_ArrayDimFetch'; } } php-parser/lib/PhpParser/Node/Expr/Variable.php000064400000001200150250175720015335 0ustar00attributes = $attributes; $this->name = $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Expr_Variable'; } } php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php000064400000001724150250175720020113 0ustar00attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames() : array { return ['var', 'name']; } public function getType() : string { return 'Expr_NullsafePropertyFetch'; } } php-parser/lib/PhpParser/Node/Expr/Closure.php000064400000005152150250175720015236 0ustar00 false : Whether the closure is static * 'byRef' => false : Whether to return by reference * 'params' => array(): Parameters * 'uses' => array(): use()s * 'returnType' => null : Return type * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attributes groups * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->static = $subNodes['static'] ?? false; $this->byRef = $subNodes['byRef'] ?? false; $this->params = $subNodes['params'] ?? []; $this->uses = $subNodes['uses'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } /** @return Node\Stmt[] */ public function getStmts() : array { return $this->stmts; } public function getAttrGroups() : array { return $this->attrGroups; } public function getType() : string { return 'Expr_Closure'; } } php-parser/lib/PhpParser/Node/Expr/Ternary.php000064400000001731150250175720015245 0ustar00attributes = $attributes; $this->cond = $cond; $this->if = $if; $this->else = $else; } public function getSubNodeNames() : array { return ['cond', 'if', 'else']; } public function getType() : string { return 'Expr_Ternary'; } } php-parser/lib/PhpParser/Node/Expr/Include_.php000064400000001630150250175720015341 0ustar00attributes = $attributes; $this->expr = $expr; $this->type = $type; } public function getSubNodeNames() : array { return ['expr', 'type']; } public function getType() : string { return 'Expr_Include'; } } php-parser/lib/PhpParser/Node/Expr/ArrayItem.php000064400000002135150250175720015515 0ustar00attributes = $attributes; $this->key = $key; $this->value = $value; $this->byRef = $byRef; $this->unpack = $unpack; } public function getSubNodeNames() : array { return ['key', 'value', 'byRef', 'unpack']; } public function getType() : string { return 'Expr_ArrayItem'; } } php-parser/lib/PhpParser/Node/Expr/Throw_.php000064400000001217150250175720015062 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Throw'; } } php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php000064400000001717150250175720016653 0ustar00attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames() : array { return ['class', 'name']; } public function getType() : string { return 'Expr_ClassConstFetch'; } } php-parser/lib/PhpParser/Node/Expr/CallLike.php000064400000001771150250175720015305 0ustar00 */ abstract public function getRawArgs(): array; /** * Returns whether this call expression is actually a first class callable. */ public function isFirstClassCallable(): bool { foreach ($this->getRawArgs() as $arg) { if ($arg instanceof VariadicPlaceholder) { return true; } } return false; } /** * Assert that this is not a first-class callable and return only ordinary Args. * * @return Arg[] */ public function getArgs(): array { assert(!$this->isFirstClassCallable()); return $this->getRawArgs(); } }php-parser/lib/PhpParser/Node/Expr/PreInc.php000064400000001166150250175720015003 0ustar00attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PreInc'; } } php-parser/lib/PhpParser/Node/Expr/Yield_.php000064400000001507150250175720015027 0ustar00attributes = $attributes; $this->key = $key; $this->value = $value; } public function getSubNodeNames() : array { return ['key', 'value']; } public function getType() : string { return 'Expr_Yield'; } } php-parser/lib/PhpParser/Node/Expr/Eval_.php000064400000001166150250175720014651 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Eval'; } } php-parser/lib/PhpParser/Node/Expr/MethodCall.php000064400000002436150250175720015640 0ustar00 Arguments */ public $args; /** * Constructs a function call node. * * @param Expr $var Variable holding object * @param string|Identifier|Expr $name Method name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames() : array { return ['var', 'name', 'args']; } public function getType() : string { return 'Expr_MethodCall'; } public function getRawArgs(): array { return $this->args; } } php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php000064400000001205150250175720015704 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_BitwiseNot'; } } php-parser/lib/PhpParser/Node/Expr/Array_.php000064400000001435150250175720015037 0ustar00attributes = $attributes; $this->items = $items; } public function getSubNodeNames() : array { return ['items']; } public function getType() : string { return 'Expr_Array'; } } php-parser/lib/PhpParser/Node/Expr/Error.php000064400000001354150250175720014713 0ustar00attributes = $attributes; } public function getSubNodeNames() : array { return []; } public function getType() : string { return 'Expr_Error'; } } php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php000064400000001217150250175720015562 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_UnaryPlus'; } } php-parser/lib/PhpParser/Node/Expr/Print_.php000064400000001171150250175720015052 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Print'; } } php-parser/lib/PhpParser/Node/Expr/PostDec.php000064400000001171150250175720015160 0ustar00attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PostDec'; } } php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php000064400000000336150250175720016066 0ustar00attributes = $attributes; $this->parts = $parts; } public function getSubNodeNames() : array { return ['parts']; } public function getType() : string { return 'Expr_ShellExec'; } } php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php000064400000001217150250175720016456 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_ErrorSuppress'; } } php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php000064400000002001150250175720017556 0ustar00attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name; } public function getSubNodeNames() : array { return ['class', 'name']; } public function getType() : string { return 'Expr_StaticPropertyFetch'; } } php-parser/lib/PhpParser/Node/Expr/ClosureUse.php000064400000001561150250175720015713 0ustar00attributes = $attributes; $this->var = $var; $this->byRef = $byRef; } public function getSubNodeNames() : array { return ['var', 'byRef']; } public function getType() : string { return 'Expr_ClosureUse'; } } php-parser/lib/PhpParser/Node/Expr/Match_.php000064400000001211150250175720015005 0ustar00attributes = $attributes; $this->cond = $cond; $this->arms = $arms; } public function getSubNodeNames() : array { return ['cond', 'arms']; } public function getType() : string { return 'Expr_Match'; } } php-parser/lib/PhpParser/Node/Expr/YieldFrom.php000064400000001223150250175720015507 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_YieldFrom'; } } php-parser/lib/PhpParser/Node/Expr/Exit_.php000064400000001361150250175720014670 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Exit'; } } php-parser/lib/PhpParser/Node/Expr/ConstFetch.php000064400000001244150250175720015660 0ustar00attributes = $attributes; $this->name = $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Expr_ConstFetch'; } } php-parser/lib/PhpParser/Node/Expr/AssignOp.php000064400000001315150250175720015342 0ustar00attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames() : array { return ['var', 'expr']; } } php-parser/lib/PhpParser/Node/Expr/List_.php000064400000001321150250175720014666 0ustar00attributes = $attributes; $this->items = $items; } public function getSubNodeNames() : array { return ['items']; } public function getType() : string { return 'Expr_List'; } } php-parser/lib/PhpParser/Node/Expr/Instanceof_.php000064400000001504150250175720016047 0ustar00attributes = $attributes; $this->expr = $expr; $this->class = $class; } public function getSubNodeNames() : array { return ['expr', 'class']; } public function getType() : string { return 'Expr_Instanceof'; } } php-parser/lib/PhpParser/Node/Expr/New_.php000064400000002132150250175720014505 0ustar00 Arguments */ public $args; /** * Constructs a function call node. * * @param Node\Name|Expr|Node\Stmt\Class_ $class Class name (or class node for anonymous classes) * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct($class, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->class = $class; $this->args = $args; } public function getSubNodeNames() : array { return ['class', 'args']; } public function getType() : string { return 'Expr_New'; } public function getRawArgs(): array { return $this->args; } } php-parser/lib/PhpParser/Node/Expr/BinaryOp.php000064400000002132150250175720015340 0ustar00attributes = $attributes; $this->left = $left; $this->right = $right; } public function getSubNodeNames() : array { return ['left', 'right']; } /** * Get the operator sigil for this binary operation. * * In the case there are multiple possible sigils for an operator, this method does not * necessarily return the one used in the parsed code. * * @return string */ abstract public function getOperatorSigil() : string; } php-parser/lib/PhpParser/Node/Expr/BooleanNot.php000064400000001222150250175720015654 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_BooleanNot'; } } php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php000064400000004522150250175720016422 0ustar00 false : Whether the closure is static * 'byRef' => false : Whether to return by reference * 'params' => array() : Parameters * 'returnType' => null : Return type * 'expr' => Expr : Expression body * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->static = $subNodes['static'] ?? false; $this->byRef = $subNodes['byRef'] ?? false; $this->params = $subNodes['params'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; $this->expr = $subNodes['expr']; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getAttrGroups() : array { return $this->attrGroups; } /** * @return Node\Stmt\Return_[] */ public function getStmts() : array { return [new Node\Stmt\Return_($this->expr)]; } public function getType() : string { return 'Expr_ArrowFunction'; } } php-parser/lib/PhpParser/Node/Expr/Isset_.php000064400000001172150250175720015046 0ustar00attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Expr_Isset'; } } php-parser/lib/PhpParser/Node/Expr/Cast.php000064400000001053150250175720014510 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } } php-parser/lib/PhpParser/Node/Expr/Clone_.php000064400000001166150250175720015022 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Clone'; } } php-parser/lib/PhpParser/Node/Expr/Assign.php000064400000001402150250175720015040 0ustar00attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames() : array { return ['var', 'expr']; } public function getType() : string { return 'Expr_Assign'; } } php-parser/lib/PhpParser/Node/Expr/Empty_.php000064400000001171150250175720015054 0ustar00attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Empty'; } } php-parser/lib/PhpParser/Builder.php000064400000000313150250175720013377 0ustar00filterCallback = $filterCallback; } /** * Get found node satisfying the filter callback. * * Returns null if no node satisfies the filter callback. * * @return null|Node Found node (or null if not found) */ public function getFoundNode() { return $this->foundNode; } public function beforeTraverse(array $nodes) { $this->foundNode = null; return null; } public function enterNode(Node $node) { $filterCallback = $this->filterCallback; if ($filterCallback($node)) { $this->foundNode = $node; return NodeTraverser::STOP_TRAVERSAL; } return null; } } php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php000064400000002142150250175720017216 0ustar00filterCallback = $filterCallback; } /** * Get found nodes satisfying the filter callback. * * Nodes are returned in pre-order. * * @return Node[] Found nodes */ public function getFoundNodes() : array { return $this->foundNodes; } public function beforeTraverse(array $nodes) { $this->foundNodes = []; return null; } public function enterNode(Node $node) { $filterCallback = $this->filterCallback; if ($filterCallback($node)) { $this->foundNodes[] = $node; } return null; } } php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php000064400000002560150250175720020541 0ustar00$node->getAttribute('parent'), the previous * node can be accessed through $node->getAttribute('previous'), * and the next node can be accessed through $node->getAttribute('next'). */ final class NodeConnectingVisitor extends NodeVisitorAbstract { /** * @var Node[] */ private $stack = []; /** * @var ?Node */ private $previous; public function beforeTraverse(array $nodes) { $this->stack = []; $this->previous = null; } public function enterNode(Node $node) { if (!empty($this->stack)) { $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); } if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) { $node->setAttribute('previous', $this->previous); $this->previous->setAttribute('next', $node); } $this->stack[] = $node; } public function leaveNode(Node $node) { $this->previous = $node; array_pop($this->stack); } } php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php000064400000000766150250175720017243 0ustar00setAttribute('origNode', $origNode); return $node; } } php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php000064400000001541150250175720021103 0ustar00$node->getAttribute('parent'). */ final class ParentConnectingVisitor extends NodeVisitorAbstract { /** * @var Node[] */ private $stack = []; public function beforeTraverse(array $nodes) { $this->stack = []; } public function enterNode(Node $node) { if (!empty($this->stack)) { $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); } $this->stack[] = $node; } public function leaveNode(Node $node) { array_pop($this->stack); } } php-parser/lib/PhpParser/NodeVisitor/NameResolver.php000064400000022651150250175720016671 0ustar00nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing); $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false; $this->replaceNodes = $options['replaceNodes'] ?? true; } /** * Get name resolution context. * * @return NameContext */ public function getNameContext() : NameContext { return $this->nameContext; } public function beforeTraverse(array $nodes) { $this->nameContext->startNamespace(); return null; } public function enterNode(Node $node) { if ($node instanceof Stmt\Namespace_) { $this->nameContext->startNamespace($node->name); } elseif ($node instanceof Stmt\Use_) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, null); } } elseif ($node instanceof Stmt\GroupUse) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, $node->prefix); } } elseif ($node instanceof Stmt\Class_) { if (null !== $node->extends) { $node->extends = $this->resolveClassName($node->extends); } foreach ($node->implements as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); if (null !== $node->name) { $this->addNamespacedName($node); } } elseif ($node instanceof Stmt\Interface_) { foreach ($node->extends as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof Stmt\Enum_) { foreach ($node->implements as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); if (null !== $node->name) { $this->addNamespacedName($node); } } elseif ($node instanceof Stmt\Trait_) { $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof Stmt\Function_) { $this->resolveSignature($node); $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof Stmt\ClassMethod || $node instanceof Expr\Closure || $node instanceof Expr\ArrowFunction ) { $this->resolveSignature($node); $this->resolveAttrGroups($node); } elseif ($node instanceof Stmt\Property) { if (null !== $node->type) { $node->type = $this->resolveType($node->type); } $this->resolveAttrGroups($node); } elseif ($node instanceof Stmt\Const_) { foreach ($node->consts as $const) { $this->addNamespacedName($const); } } else if ($node instanceof Stmt\ClassConst) { $this->resolveAttrGroups($node); } else if ($node instanceof Stmt\EnumCase) { $this->resolveAttrGroups($node); } elseif ($node instanceof Expr\StaticCall || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\ClassConstFetch || $node instanceof Expr\New_ || $node instanceof Expr\Instanceof_ ) { if ($node->class instanceof Name) { $node->class = $this->resolveClassName($node->class); } } elseif ($node instanceof Stmt\Catch_) { foreach ($node->types as &$type) { $type = $this->resolveClassName($type); } } elseif ($node instanceof Expr\FuncCall) { if ($node->name instanceof Name) { $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION); } } elseif ($node instanceof Expr\ConstFetch) { $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT); } elseif ($node instanceof Stmt\TraitUse) { foreach ($node->traits as &$trait) { $trait = $this->resolveClassName($trait); } foreach ($node->adaptations as $adaptation) { if (null !== $adaptation->trait) { $adaptation->trait = $this->resolveClassName($adaptation->trait); } if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { foreach ($adaptation->insteadof as &$insteadof) { $insteadof = $this->resolveClassName($insteadof); } } } } return null; } private function addAlias(Stmt\UseUse $use, int $type, Name $prefix = null) { // Add prefix for group uses $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; // Type is determined either by individual element or whole use declaration $type |= $use->type; $this->nameContext->addAlias( $name, (string) $use->getAlias(), $type, $use->getAttributes() ); } /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ private function resolveSignature($node) { foreach ($node->params as $param) { $param->type = $this->resolveType($param->type); $this->resolveAttrGroups($param); } $node->returnType = $this->resolveType($node->returnType); } private function resolveType($node) { if ($node instanceof Name) { return $this->resolveClassName($node); } if ($node instanceof Node\NullableType) { $node->type = $this->resolveType($node->type); return $node; } if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { foreach ($node->types as &$type) { $type = $this->resolveType($type); } return $node; } return $node; } /** * Resolve name, according to name resolver options. * * @param Name $name Function or constant name to resolve * @param int $type One of Stmt\Use_::TYPE_* * * @return Name Resolved name, or original name with attribute */ protected function resolveName(Name $name, int $type) : Name { if (!$this->replaceNodes) { $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { $name->setAttribute('resolvedName', $resolvedName); } else { $name->setAttribute('namespacedName', FullyQualified::concat( $this->nameContext->getNamespace(), $name, $name->getAttributes())); } return $name; } if ($this->preserveOriginalNames) { // Save the original name $originalName = $name; $name = clone $originalName; $name->setAttribute('originalName', $originalName); } $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { return $resolvedName; } // unqualified names inside a namespace cannot be resolved at compile-time // add the namespaced version of the name as an attribute $name->setAttribute('namespacedName', FullyQualified::concat( $this->nameContext->getNamespace(), $name, $name->getAttributes())); return $name; } protected function resolveClassName(Name $name) { return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); } protected function addNamespacedName(Node $node) { $node->namespacedName = Name::concat( $this->nameContext->getNamespace(), (string) $node->name); } protected function resolveAttrGroups(Node $node) { foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { $attr->name = $this->resolveClassName($attr->name); } } } } php-parser/lib/PhpParser/Error.php000064400000011662150250175720013113 0ustar00rawMessage = $message; if (is_array($attributes)) { $this->attributes = $attributes; } else { $this->attributes = ['startLine' => $attributes]; } $this->updateMessage(); } /** * Gets the error message * * @return string Error message */ public function getRawMessage() : string { return $this->rawMessage; } /** * Gets the line the error starts in. * * @return int Error start line */ public function getStartLine() : int { return $this->attributes['startLine'] ?? -1; } /** * Gets the line the error ends in. * * @return int Error end line */ public function getEndLine() : int { return $this->attributes['endLine'] ?? -1; } /** * Gets the attributes of the node/token the error occurred at. * * @return array */ public function getAttributes() : array { return $this->attributes; } /** * Sets the attributes of the node/token the error occurred at. * * @param array $attributes */ public function setAttributes(array $attributes) { $this->attributes = $attributes; $this->updateMessage(); } /** * Sets the line of the PHP file the error occurred in. * * @param string $message Error message */ public function setRawMessage(string $message) { $this->rawMessage = $message; $this->updateMessage(); } /** * Sets the line the error starts in. * * @param int $line Error start line */ public function setStartLine(int $line) { $this->attributes['startLine'] = $line; $this->updateMessage(); } /** * Returns whether the error has start and end column information. * * For column information enable the startFilePos and endFilePos in the lexer options. * * @return bool */ public function hasColumnInfo() : bool { return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']); } /** * Gets the start column (1-based) into the line where the error started. * * @param string $code Source code of the file * @return int */ public function getStartColumn(string $code) : int { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['startFilePos']); } /** * Gets the end column (1-based) into the line where the error ended. * * @param string $code Source code of the file * @return int */ public function getEndColumn(string $code) : int { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['endFilePos']); } /** * Formats message including line and column information. * * @param string $code Source code associated with the error, for calculation of the columns * * @return string Formatted message */ public function getMessageWithColumnInfo(string $code) : string { return sprintf( '%s from %d:%d to %d:%d', $this->getRawMessage(), $this->getStartLine(), $this->getStartColumn($code), $this->getEndLine(), $this->getEndColumn($code) ); } /** * Converts a file offset into a column. * * @param string $code Source code that $pos indexes into * @param int $pos 0-based position in $code * * @return int 1-based column (relative to start of line) */ private function toColumn(string $code, int $pos) : int { if ($pos > strlen($code)) { throw new \RuntimeException('Invalid position information'); } $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); if (false === $lineStartPos) { $lineStartPos = -1; } return $pos - $lineStartPos; } /** * Updates the exception message after a change to rawMessage or rawLine. */ protected function updateMessage() { $this->message = $this->rawMessage; if (-1 === $this->getStartLine()) { $this->message .= ' on unknown line'; } else { $this->message .= ' on line ' . $this->getStartLine(); } } } php-parser/lib/PhpParser/NodeAbstract.php000064400000012034150250175720014365 0ustar00attributes = $attributes; } /** * Gets line the node started in (alias of getStartLine). * * @return int Start line (or -1 if not available) */ public function getLine() : int { return $this->attributes['startLine'] ?? -1; } /** * Gets line the node started in. * * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). * * @return int Start line (or -1 if not available) */ public function getStartLine() : int { return $this->attributes['startLine'] ?? -1; } /** * Gets the line the node ended in. * * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). * * @return int End line (or -1 if not available) */ public function getEndLine() : int { return $this->attributes['endLine'] ?? -1; } /** * Gets the token offset of the first token that is part of this node. * * The offset is an index into the array returned by Lexer::getTokens(). * * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). * * @return int Token start position (or -1 if not available) */ public function getStartTokenPos() : int { return $this->attributes['startTokenPos'] ?? -1; } /** * Gets the token offset of the last token that is part of this node. * * The offset is an index into the array returned by Lexer::getTokens(). * * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). * * @return int Token end position (or -1 if not available) */ public function getEndTokenPos() : int { return $this->attributes['endTokenPos'] ?? -1; } /** * Gets the file offset of the first character that is part of this node. * * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). * * @return int File start position (or -1 if not available) */ public function getStartFilePos() : int { return $this->attributes['startFilePos'] ?? -1; } /** * Gets the file offset of the last character that is part of this node. * * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). * * @return int File end position (or -1 if not available) */ public function getEndFilePos() : int { return $this->attributes['endFilePos'] ?? -1; } /** * Gets all comments directly preceding this node. * * The comments are also available through the "comments" attribute. * * @return Comment[] */ public function getComments() : array { return $this->attributes['comments'] ?? []; } /** * Gets the doc comment of the node. * * @return null|Comment\Doc Doc comment object or null */ public function getDocComment() { $comments = $this->getComments(); for ($i = count($comments) - 1; $i >= 0; $i--) { $comment = $comments[$i]; if ($comment instanceof Comment\Doc) { return $comment; } } return null; } /** * Sets the doc comment of the node. * * This will either replace an existing doc comment or add it to the comments array. * * @param Comment\Doc $docComment Doc comment to set */ public function setDocComment(Comment\Doc $docComment) { $comments = $this->getComments(); for ($i = count($comments) - 1; $i >= 0; $i--) { if ($comments[$i] instanceof Comment\Doc) { // Replace existing doc comment. $comments[$i] = $docComment; $this->setAttribute('comments', $comments); return; } } // Append new doc comment. $comments[] = $docComment; $this->setAttribute('comments', $comments); } public function setAttribute(string $key, $value) { $this->attributes[$key] = $value; } public function hasAttribute(string $key) : bool { return array_key_exists($key, $this->attributes); } public function getAttribute(string $key, $default = null) { if (array_key_exists($key, $this->attributes)) { return $this->attributes[$key]; } return $default; } public function getAttributes() : array { return $this->attributes; } public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * @return array */ public function jsonSerialize() : array { return ['nodeType' => $this->getType()] + get_object_vars($this); } } php-parser/lib/PhpParser/NodeFinder.php000064400000004624150250175720014037 0ustar00addVisitor($visitor); $traverser->traverse($nodes); return $visitor->getFoundNodes(); } /** * Find all nodes that are instances of a certain class. * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param string $class Class name * * @return Node[] Found nodes (all instances of $class) */ public function findInstanceOf($nodes, string $class) : array { return $this->find($nodes, function ($node) use ($class) { return $node instanceof $class; }); } /** * Find first node satisfying a filter callback. * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param callable $filter Filter callback: function(Node $node) : bool * * @return null|Node Found node (or null if none found) */ public function findFirst($nodes, callable $filter) { if (!is_array($nodes)) { $nodes = [$nodes]; } $visitor = new FirstFindingVisitor($filter); $traverser = new NodeTraverser; $traverser->addVisitor($visitor); $traverser->traverse($nodes); return $visitor->getFoundNode(); } /** * Find first node that is an instance of a certain class. * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param string $class Class name * * @return null|Node Found node, which is an instance of $class (or null if none found) */ public function findFirstInstanceOf($nodes, string $class) { return $this->findFirst($nodes, function ($node) use ($class) { return $node instanceof $class; }); } } php-parser/lib/PhpParser/NodeDumper.php000064400000015303150250175720014060 0ustar00dumpComments = !empty($options['dumpComments']); $this->dumpPositions = !empty($options['dumpPositions']); } /** * Dumps a node or array. * * @param array|Node $node Node or array to dump * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if * the dumpPositions option is enabled and the dumping of node offsets * is desired. * * @return string Dumped value */ public function dump($node, string $code = null) : string { $this->code = $code; return $this->dumpRecursive($node); } protected function dumpRecursive($node) { if ($node instanceof Node) { $r = $node->getType(); if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) { $r .= $p; } $r .= '('; foreach ($node->getSubNodeNames() as $key) { $r .= "\n " . $key . ': '; $value = $node->$key; if (null === $value) { $r .= 'null'; } elseif (false === $value) { $r .= 'false'; } elseif (true === $value) { $r .= 'true'; } elseif (is_scalar($value)) { if ('flags' === $key || 'newModifier' === $key) { $r .= $this->dumpFlags($value); } elseif ('type' === $key && $node instanceof Include_) { $r .= $this->dumpIncludeType($value); } elseif ('type' === $key && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) { $r .= $this->dumpUseType($value); } else { $r .= $value; } } else { $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); } } if ($this->dumpComments && $comments = $node->getComments()) { $r .= "\n comments: " . str_replace("\n", "\n ", $this->dumpRecursive($comments)); } } elseif (is_array($node)) { $r = 'array('; foreach ($node as $key => $value) { $r .= "\n " . $key . ': '; if (null === $value) { $r .= 'null'; } elseif (false === $value) { $r .= 'false'; } elseif (true === $value) { $r .= 'true'; } elseif (is_scalar($value)) { $r .= $value; } else { $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); } } } elseif ($node instanceof Comment) { return $node->getReformattedText(); } else { throw new \InvalidArgumentException('Can only dump nodes and arrays.'); } return $r . "\n)"; } protected function dumpFlags($flags) { $strs = []; if ($flags & Class_::MODIFIER_PUBLIC) { $strs[] = 'MODIFIER_PUBLIC'; } if ($flags & Class_::MODIFIER_PROTECTED) { $strs[] = 'MODIFIER_PROTECTED'; } if ($flags & Class_::MODIFIER_PRIVATE) { $strs[] = 'MODIFIER_PRIVATE'; } if ($flags & Class_::MODIFIER_ABSTRACT) { $strs[] = 'MODIFIER_ABSTRACT'; } if ($flags & Class_::MODIFIER_STATIC) { $strs[] = 'MODIFIER_STATIC'; } if ($flags & Class_::MODIFIER_FINAL) { $strs[] = 'MODIFIER_FINAL'; } if ($flags & Class_::MODIFIER_READONLY) { $strs[] = 'MODIFIER_READONLY'; } if ($strs) { return implode(' | ', $strs) . ' (' . $flags . ')'; } else { return $flags; } } protected function dumpIncludeType($type) { $map = [ Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE', ]; if (!isset($map[$type])) { return $type; } return $map[$type] . ' (' . $type . ')'; } protected function dumpUseType($type) { $map = [ Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', Use_::TYPE_NORMAL => 'TYPE_NORMAL', Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', Use_::TYPE_CONSTANT => 'TYPE_CONSTANT', ]; if (!isset($map[$type])) { return $type; } return $map[$type] . ' (' . $type . ')'; } /** * Dump node position, if possible. * * @param Node $node Node for which to dump position * * @return string|null Dump of position, or null if position information not available */ protected function dumpPosition(Node $node) { if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) { return null; } $start = $node->getStartLine(); $end = $node->getEndLine(); if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') && null !== $this->code ) { $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos()); $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos()); } return "[$start - $end]"; } // Copied from Error class private function toColumn($code, $pos) { if ($pos > strlen($code)) { throw new \RuntimeException('Invalid position information'); } $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); if (false === $lineStartPos) { $lineStartPos = -1; } return $pos - $lineStartPos; } } php-parser/lib/PhpParser/ErrorHandler/Collecting.php000064400000001560150250175720016470 0ustar00errors[] = $error; } /** * Get collected errors. * * @return Error[] */ public function getErrors() : array { return $this->errors; } /** * Check whether there are any errors. * * @return bool */ public function hasErrors() : bool { return !empty($this->errors); } /** * Reset/clear collected errors. */ public function clearErrors() { $this->errors = []; } } php-parser/lib/PhpParser/ErrorHandler/Throwing.php000064400000000552150250175720016206 0ustar00text = $text; $this->startLine = $startLine; $this->startFilePos = $startFilePos; $this->startTokenPos = $startTokenPos; $this->endLine = $endLine; $this->endFilePos = $endFilePos; $this->endTokenPos = $endTokenPos; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function getText() : string { return $this->text; } /** * Gets the line number the comment started on. * * @return int Line number (or -1 if not available) */ public function getStartLine() : int { return $this->startLine; } /** * Gets the file offset the comment started on. * * @return int File offset (or -1 if not available) */ public function getStartFilePos() : int { return $this->startFilePos; } /** * Gets the token offset the comment started on. * * @return int Token offset (or -1 if not available) */ public function getStartTokenPos() : int { return $this->startTokenPos; } /** * Gets the line number the comment ends on. * * @return int Line number (or -1 if not available) */ public function getEndLine() : int { return $this->endLine; } /** * Gets the file offset the comment ends on. * * @return int File offset (or -1 if not available) */ public function getEndFilePos() : int { return $this->endFilePos; } /** * Gets the token offset the comment ends on. * * @return int Token offset (or -1 if not available) */ public function getEndTokenPos() : int { return $this->endTokenPos; } /** * Gets the line number the comment started on. * * @deprecated Use getStartLine() instead * * @return int Line number */ public function getLine() : int { return $this->startLine; } /** * Gets the file offset the comment started on. * * @deprecated Use getStartFilePos() instead * * @return int File offset */ public function getFilePos() : int { return $this->startFilePos; } /** * Gets the token offset the comment started on. * * @deprecated Use getStartTokenPos() instead * * @return int Token offset */ public function getTokenPos() : int { return $this->startTokenPos; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function __toString() : string { return $this->text; } /** * Gets the reformatted comment text. * * "Reformatted" here means that we try to clean up the whitespace at the * starts of the lines. This is necessary because we receive the comments * without trailing whitespace on the first line, but with trailing whitespace * on all subsequent lines. * * @return mixed|string */ public function getReformattedText() { $text = trim($this->text); $newlinePos = strpos($text, "\n"); if (false === $newlinePos) { // Single line comments don't need further processing return $text; } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) { // Multi line comment of the type // // /* // * Some text. // * Some more text. // */ // // is handled by replacing the whitespace sequences before the * by a single space return preg_replace('(^\s+\*)m', ' *', $this->text); } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) { // Multi line comment of the type // // /* // Some text. // Some more text. // */ // // is handled by removing the whitespace sequence on the line before the closing // */ on all lines. So if the last line is " */", then " " is removed at the // start of all lines. return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text); } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) { // Multi line comment of the type // // /* Some text. // Some more text. // Indented text. // Even more text. */ // // is handled by removing the difference between the shortest whitespace prefix on all // lines and the length of the "/* " opening sequence. $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1)); $removeLen = $prefixLen - strlen($matches[0]); return preg_replace('(^\s{' . $removeLen . '})m', '', $text); } // No idea how to format this comment, so simply return as is return $text; } /** * Get length of shortest whitespace prefix (at the start of a line). * * If there is a line with no prefix whitespace, 0 is a valid return value. * * @param string $str String to check * @return int Length in characters. Tabs count as single characters. */ private function getShortestWhitespacePrefixLen(string $str) : int { $lines = explode("\n", $str); $shortestPrefixLen = \INF; foreach ($lines as $line) { preg_match('(^\s*)', $line, $matches); $prefixLen = strlen($matches[0]); if ($prefixLen < $shortestPrefixLen) { $shortestPrefixLen = $prefixLen; } } return $shortestPrefixLen; } /** * @return array * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed} */ public function jsonSerialize() : array { // Technically not a node, but we make it look like one anyway $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment'; return [ 'nodeType' => $type, 'text' => $this->text, // TODO: Rename these to include "start". 'line' => $this->startLine, 'filePos' => $this->startFilePos, 'tokenPos' => $this->startTokenPos, 'endLine' => $this->endLine, 'endFilePos' => $this->endFilePos, 'endTokenPos' => $this->endTokenPos, ]; } } php-parser/lib/PhpParser/JsonDecoder.php000064400000006457150250175720014227 0ustar00decodeRecursive($value); } private function decodeRecursive($value) { if (\is_array($value)) { if (isset($value['nodeType'])) { if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') { return $this->decodeComment($value); } return $this->decodeNode($value); } return $this->decodeArray($value); } return $value; } private function decodeArray(array $array) : array { $decodedArray = []; foreach ($array as $key => $value) { $decodedArray[$key] = $this->decodeRecursive($value); } return $decodedArray; } private function decodeNode(array $value) : Node { $nodeType = $value['nodeType']; if (!\is_string($nodeType)) { throw new \RuntimeException('Node type must be a string'); } $reflectionClass = $this->reflectionClassFromNodeType($nodeType); /** @var Node $node */ $node = $reflectionClass->newInstanceWithoutConstructor(); if (isset($value['attributes'])) { if (!\is_array($value['attributes'])) { throw new \RuntimeException('Attributes must be an array'); } $node->setAttributes($this->decodeArray($value['attributes'])); } foreach ($value as $name => $subNode) { if ($name === 'nodeType' || $name === 'attributes') { continue; } $node->$name = $this->decodeRecursive($subNode); } return $node; } private function decodeComment(array $value) : Comment { $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class; if (!isset($value['text'])) { throw new \RuntimeException('Comment must have text'); } return new $className( $value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1, $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1 ); } private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass { if (!isset($this->reflectionClassCache[$nodeType])) { $className = $this->classNameFromNodeType($nodeType); $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className); } return $this->reflectionClassCache[$nodeType]; } private function classNameFromNodeType(string $nodeType) : string { $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\'); if (class_exists($className)) { return $className; } $className .= '_'; if (class_exists($className)) { return $className; } throw new \RuntimeException("Unknown node type \"$nodeType\""); } } php-parser/lib/PhpParser/ConstExprEvaluator.php000064400000022066150250175720015632 0ustar00fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) { throw new ConstExprEvaluationException( "Expression of type {$expr->getType()} cannot be evaluated" ); }; } /** * Silently evaluates a constant expression into a PHP value. * * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException. * The original source of the exception is available through getPrevious(). * * If some part of the expression cannot be evaluated, the fallback evaluator passed to the * constructor will be invoked. By default, if no fallback is provided, an exception of type * ConstExprEvaluationException is thrown. * * See class doc comment for caveats and limitations. * * @param Expr $expr Constant expression to evaluate * @return mixed Result of evaluation * * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred */ public function evaluateSilently(Expr $expr) { set_error_handler(function($num, $str, $file, $line) { throw new \ErrorException($str, 0, $num, $file, $line); }); try { return $this->evaluate($expr); } catch (\Throwable $e) { if (!$e instanceof ConstExprEvaluationException) { $e = new ConstExprEvaluationException( "An error occurred during constant expression evaluation", 0, $e); } throw $e; } finally { restore_error_handler(); } } /** * Directly evaluates a constant expression into a PHP value. * * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these * into a ConstExprEvaluationException. * * If some part of the expression cannot be evaluated, the fallback evaluator passed to the * constructor will be invoked. By default, if no fallback is provided, an exception of type * ConstExprEvaluationException is thrown. * * See class doc comment for caveats and limitations. * * @param Expr $expr Constant expression to evaluate * @return mixed Result of evaluation * * @throws ConstExprEvaluationException if the expression cannot be evaluated */ public function evaluateDirectly(Expr $expr) { return $this->evaluate($expr); } private function evaluate(Expr $expr) { if ($expr instanceof Scalar\LNumber || $expr instanceof Scalar\DNumber || $expr instanceof Scalar\String_ ) { return $expr->value; } if ($expr instanceof Expr\Array_) { return $this->evaluateArray($expr); } // Unary operators if ($expr instanceof Expr\UnaryPlus) { return +$this->evaluate($expr->expr); } if ($expr instanceof Expr\UnaryMinus) { return -$this->evaluate($expr->expr); } if ($expr instanceof Expr\BooleanNot) { return !$this->evaluate($expr->expr); } if ($expr instanceof Expr\BitwiseNot) { return ~$this->evaluate($expr->expr); } if ($expr instanceof Expr\BinaryOp) { return $this->evaluateBinaryOp($expr); } if ($expr instanceof Expr\Ternary) { return $this->evaluateTernary($expr); } if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) { return $this->evaluate($expr->var)[$this->evaluate($expr->dim)]; } if ($expr instanceof Expr\ConstFetch) { return $this->evaluateConstFetch($expr); } return ($this->fallbackEvaluator)($expr); } private function evaluateArray(Expr\Array_ $expr) { $array = []; foreach ($expr->items as $item) { if (null !== $item->key) { $array[$this->evaluate($item->key)] = $this->evaluate($item->value); } elseif ($item->unpack) { $array = array_merge($array, $this->evaluate($item->value)); } else { $array[] = $this->evaluate($item->value); } } return $array; } private function evaluateTernary(Expr\Ternary $expr) { if (null === $expr->if) { return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else); } return $this->evaluate($expr->cond) ? $this->evaluate($expr->if) : $this->evaluate($expr->else); } private function evaluateBinaryOp(Expr\BinaryOp $expr) { if ($expr instanceof Expr\BinaryOp\Coalesce && $expr->left instanceof Expr\ArrayDimFetch ) { // This needs to be special cased to respect BP_VAR_IS fetch semantics return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)] ?? $this->evaluate($expr->right); } // The evaluate() calls are repeated in each branch, because some of the operators are // short-circuiting and evaluating the RHS in advance may be illegal in that case $l = $expr->left; $r = $expr->right; switch ($expr->getOperatorSigil()) { case '&': return $this->evaluate($l) & $this->evaluate($r); case '|': return $this->evaluate($l) | $this->evaluate($r); case '^': return $this->evaluate($l) ^ $this->evaluate($r); case '&&': return $this->evaluate($l) && $this->evaluate($r); case '||': return $this->evaluate($l) || $this->evaluate($r); case '??': return $this->evaluate($l) ?? $this->evaluate($r); case '.': return $this->evaluate($l) . $this->evaluate($r); case '/': return $this->evaluate($l) / $this->evaluate($r); case '==': return $this->evaluate($l) == $this->evaluate($r); case '>': return $this->evaluate($l) > $this->evaluate($r); case '>=': return $this->evaluate($l) >= $this->evaluate($r); case '===': return $this->evaluate($l) === $this->evaluate($r); case 'and': return $this->evaluate($l) and $this->evaluate($r); case 'or': return $this->evaluate($l) or $this->evaluate($r); case 'xor': return $this->evaluate($l) xor $this->evaluate($r); case '-': return $this->evaluate($l) - $this->evaluate($r); case '%': return $this->evaluate($l) % $this->evaluate($r); case '*': return $this->evaluate($l) * $this->evaluate($r); case '!=': return $this->evaluate($l) != $this->evaluate($r); case '!==': return $this->evaluate($l) !== $this->evaluate($r); case '+': return $this->evaluate($l) + $this->evaluate($r); case '**': return $this->evaluate($l) ** $this->evaluate($r); case '<<': return $this->evaluate($l) << $this->evaluate($r); case '>>': return $this->evaluate($l) >> $this->evaluate($r); case '<': return $this->evaluate($l) < $this->evaluate($r); case '<=': return $this->evaluate($l) <= $this->evaluate($r); case '<=>': return $this->evaluate($l) <=> $this->evaluate($r); } throw new \Exception('Should not happen'); } private function evaluateConstFetch(Expr\ConstFetch $expr) { $name = $expr->name->toLowerString(); switch ($name) { case 'null': return null; case 'false': return false; case 'true': return true; } return ($this->fallbackEvaluator)($expr); } } php-parser/lib/PhpParser/NodeVisitor.php000064400000003752150250175720014270 0ustar00 $node stays as-is * * NodeTraverser::DONT_TRAVERSE_CHILDREN * => Children of $node are not traversed. $node stays as-is * * NodeTraverser::STOP_TRAVERSAL * => Traversal is aborted. $node stays as-is * * otherwise * => $node is set to the return value * * @param Node $node Node * * @return null|int|Node Replacement node (or special return value) */ public function enterNode(Node $node); /** * Called when leaving a node. * * Return value semantics: * * null * => $node stays as-is * * NodeTraverser::REMOVE_NODE * => $node is removed from the parent array * * NodeTraverser::STOP_TRAVERSAL * => Traversal is aborted. $node stays as-is * * array (of Nodes) * => The return value is merged into the parent array (at the position of the $node) * * otherwise * => $node is set to the return value * * @param Node $node Node * * @return null|int|Node|Node[] Replacement node (or special return value) */ public function leaveNode(Node $node); /** * Called once after traversal. * * Return value semantics: * * null: $nodes stays as-is * * otherwise: $nodes is set to the return value * * @param Node[] $nodes Array of nodes * * @return null|Node[] Array of nodes */ public function afterTraverse(array $nodes); } php-parser/lib/PhpParser/Builder/Param.php000064400000005600150250175720014443 0ustar00name = $name; } /** * Sets default value for the parameter. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = BuilderHelpers::normalizeValue($value); return $this; } /** * Sets type for the parameter. * * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type * * @return $this The builder instance (for fluid interface) */ public function setType($type) { $this->type = BuilderHelpers::normalizeType($type); if ($this->type == 'void') { throw new \LogicException('Parameter type cannot be void'); } return $this; } /** * Sets type for the parameter. * * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type * * @return $this The builder instance (for fluid interface) * * @deprecated Use setType() instead */ public function setTypeHint($type) { return $this->setType($type); } /** * Make the parameter accept the value by reference. * * @return $this The builder instance (for fluid interface) */ public function makeByRef() { $this->byRef = true; return $this; } /** * Make the parameter variadic * * @return $this The builder instance (for fluid interface) */ public function makeVariadic() { $this->variadic = true; return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built parameter node. * * @return Node\Param The built parameter node */ public function getNode() : Node { return new Node\Param( new Node\Expr\Variable($this->name), $this->default, $this->type, $this->byRef, $this->variadic, [], 0, $this->attributeGroups ); } } php-parser/lib/PhpParser/Builder/Function_.php000064400000003152150250175720015327 0ustar00name = $name; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built function node. * * @return Stmt\Function_ The built function node */ public function getNode() : Node { return new Stmt\Function_($this->name, [ 'byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts, 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } php-parser/lib/PhpParser/Builder/Declaration.php000064400000001730150250175720015630 0ustar00addStmt($stmt); } return $this; } /** * Sets doc comment for the declaration. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes['comments'] = [ BuilderHelpers::normalizeDocComment($docComment) ]; return $this; } } php-parser/lib/PhpParser/Builder/EnumCase.php000064400000003563150250175720015111 0ustar00name = $name; } /** * Sets the value. * * @param Node\Expr|string|int $value * * @return $this */ public function setValue($value) { $this->value = BuilderHelpers::normalizeValue($value); return $this; } /** * Sets doc comment for the constant. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = [ 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] ]; return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built enum case node. * * @return Stmt\EnumCase The built constant node */ public function getNode(): PhpParser\Node { return new Stmt\EnumCase( $this->name, $this->value, $this->attributeGroups, $this->attributes ); } } php-parser/lib/PhpParser/Builder/Trait_.php000064400000003751150250175720014632 0ustar00name = $name; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof Stmt\Property) { $this->properties[] = $stmt; } elseif ($stmt instanceof Stmt\ClassMethod) { $this->methods[] = $stmt; } elseif ($stmt instanceof Stmt\TraitUse) { $this->uses[] = $stmt; } else { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built trait node. * * @return Stmt\Trait_ The built interface node */ public function getNode() : PhpParser\Node { return new Stmt\Trait_( $this->name, [ 'stmts' => array_merge($this->uses, $this->properties, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes ); } } php-parser/lib/PhpParser/Builder/Namespace_.php000064400000002012150250175720015430 0ustar00name = null !== $name ? BuilderHelpers::normalizeName($name) : null; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Returns the built node. * * @return Stmt\Namespace_ The built node */ public function getNode() : Node { return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes); } } php-parser/lib/PhpParser/Builder/Enum_.php000064400000005707150250175720014456 0ustar00name = $name; } /** * Sets the scalar type. * * @param string|Identifier $type * * @return $this */ public function setScalarType($scalarType) { $this->scalarType = BuilderHelpers::normalizeType($scalarType); return $this; } /** * Implements one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to implement * * @return $this The builder instance (for fluid interface) */ public function implement(...$interfaces) { foreach ($interfaces as $interface) { $this->implements[] = BuilderHelpers::normalizeName($interface); } return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); $targets = [ Stmt\TraitUse::class => &$this->uses, Stmt\EnumCase::class => &$this->enumCases, Stmt\ClassConst::class => &$this->constants, Stmt\ClassMethod::class => &$this->methods, ]; $class = \get_class($stmt); if (!isset($targets[$class])) { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } $targets[$class][] = $stmt; return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built class node. * * @return Stmt\Enum_ The built enum node */ public function getNode() : PhpParser\Node { return new Stmt\Enum_($this->name, [ 'scalarType' => $this->scalarType, 'implements' => $this->implements, 'stmts' => array_merge($this->uses, $this->enumCases, $this->constants, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } php-parser/lib/PhpParser/Builder/TraitUse.php000064400000003045150250175720015144 0ustar00and($trait); } } /** * Adds used trait. * * @param Node\Name|string $trait Trait name * * @return $this The builder instance (for fluid interface) */ public function and($trait) { $this->traits[] = BuilderHelpers::normalizeName($trait); return $this; } /** * Adds trait adaptation. * * @param Stmt\TraitUseAdaptation|Builder\TraitUseAdaptation $adaptation Trait adaptation * * @return $this The builder instance (for fluid interface) */ public function with($adaptation) { $adaptation = BuilderHelpers::normalizeNode($adaptation); if (!$adaptation instanceof Stmt\TraitUseAdaptation) { throw new \LogicException('Adaptation must have type TraitUseAdaptation'); } $this->adaptations[] = $adaptation; return $this; } /** * Returns the built node. * * @return Node The built node */ public function getNode() : Node { return new Stmt\TraitUse($this->traits, $this->adaptations); } } php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php000064400000010130150250175720017142 0ustar00type = self::TYPE_UNDEFINED; $this->trait = is_null($trait)? null: BuilderHelpers::normalizeName($trait); $this->method = BuilderHelpers::normalizeIdentifier($method); } /** * Sets alias of method. * * @param Node\Identifier|string $alias Alias for adaptated method * * @return $this The builder instance (for fluid interface) */ public function as($alias) { if ($this->type === self::TYPE_UNDEFINED) { $this->type = self::TYPE_ALIAS; } if ($this->type !== self::TYPE_ALIAS) { throw new \LogicException('Cannot set alias for not alias adaptation buider'); } $this->alias = $alias; return $this; } /** * Sets adaptated method public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Sets adaptated method protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Sets adaptated method private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Adds overwritten traits. * * @param Node\Name|string ...$traits Traits for overwrite * * @return $this The builder instance (for fluid interface) */ public function insteadof(...$traits) { if ($this->type === self::TYPE_UNDEFINED) { if (is_null($this->trait)) { throw new \LogicException('Precedence adaptation must have trait'); } $this->type = self::TYPE_PRECEDENCE; } if ($this->type !== self::TYPE_PRECEDENCE) { throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider'); } foreach ($traits as $trait) { $this->insteadof[] = BuilderHelpers::normalizeName($trait); } return $this; } protected function setModifier(int $modifier) { if ($this->type === self::TYPE_UNDEFINED) { $this->type = self::TYPE_ALIAS; } if ($this->type !== self::TYPE_ALIAS) { throw new \LogicException('Cannot set access modifier for not alias adaptation buider'); } if (is_null($this->modifier)) { $this->modifier = $modifier; } else { throw new \LogicException('Multiple access type modifiers are not allowed'); } } /** * Returns the built node. * * @return Node The built node */ public function getNode() : Node { switch ($this->type) { case self::TYPE_ALIAS: return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias); case self::TYPE_PRECEDENCE: return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof); default: throw new \LogicException('Type of adaptation is not defined'); } } } php-parser/lib/PhpParser/Builder/Method.php000064400000007264150250175720014633 0ustar00name = $name; } /** * Makes the method public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Makes the method protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Makes the method private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Makes the method static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); return $this; } /** * Makes the method abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { if (!empty($this->stmts)) { throw new \LogicException('Cannot make method with statements abstract'); } $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); $this->stmts = null; // abstract methods don't have statements return $this; } /** * Makes the method final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); return $this; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { if (null === $this->stmts) { throw new \LogicException('Cannot add statements to an abstract method'); } $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built method node. * * @return Stmt\ClassMethod The built method node */ public function getNode() : Node { return new Stmt\ClassMethod($this->name, [ 'flags' => $this->flags, 'byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts, 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } php-parser/lib/PhpParser/Builder/Class_.php000064400000007360150250175720014614 0ustar00name = $name; } /** * Extends a class. * * @param Name|string $class Name of class to extend * * @return $this The builder instance (for fluid interface) */ public function extend($class) { $this->extends = BuilderHelpers::normalizeName($class); return $this; } /** * Implements one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to implement * * @return $this The builder instance (for fluid interface) */ public function implement(...$interfaces) { foreach ($interfaces as $interface) { $this->implements[] = BuilderHelpers::normalizeName($interface); } return $this; } /** * Makes the class abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); return $this; } /** * Makes the class final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); return $this; } public function makeReadonly() { $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); $targets = [ Stmt\TraitUse::class => &$this->uses, Stmt\ClassConst::class => &$this->constants, Stmt\Property::class => &$this->properties, Stmt\ClassMethod::class => &$this->methods, ]; $class = \get_class($stmt); if (!isset($targets[$class])) { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } $targets[$class][] = $stmt; return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built class node. * * @return Stmt\Class_ The built class node */ public function getNode() : PhpParser\Node { return new Stmt\Class_($this->name, [ 'flags' => $this->flags, 'extends' => $this->extends, 'implements' => $this->implements, 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } php-parser/lib/PhpParser/Builder/FunctionLike.php000064400000003311150250175720015772 0ustar00returnByRef = true; return $this; } /** * Adds a parameter. * * @param Node\Param|Param $param The parameter to add * * @return $this The builder instance (for fluid interface) */ public function addParam($param) { $param = BuilderHelpers::normalizeNode($param); if (!$param instanceof Node\Param) { throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType())); } $this->params[] = $param; return $this; } /** * Adds multiple parameters. * * @param array $params The parameters to add * * @return $this The builder instance (for fluid interface) */ public function addParams(array $params) { foreach ($params as $param) { $this->addParam($param); } return $this; } /** * Sets the return type for PHP 7. * * @param string|Node\Name|Node\Identifier|Node\ComplexType $type * * @return $this The builder instance (for fluid interface) */ public function setReturnType($type) { $this->returnType = BuilderHelpers::normalizeType($type); return $this; } } php-parser/lib/PhpParser/Builder/Property.php000064400000007641150250175720015236 0ustar00name = $name; } /** * Makes the property public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Makes the property protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Makes the property private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Makes the property static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); return $this; } /** * Makes the property readonly. * * @return $this The builder instance (for fluid interface) */ public function makeReadonly() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); return $this; } /** * Sets default value for the property. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = BuilderHelpers::normalizeValue($value); return $this; } /** * Sets doc comment for the property. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = [ 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] ]; return $this; } /** * Sets the property type for PHP 7.4+. * * @param string|Name|Identifier|ComplexType $type * * @return $this */ public function setType($type) { $this->type = BuilderHelpers::normalizeType($type); return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built class node. * * @return Stmt\Property The built property node */ public function getNode() : PhpParser\Node { return new Stmt\Property( $this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC, [ new Stmt\PropertyProperty($this->name, $this->default) ], $this->attributes, $this->type, $this->attributeGroups ); } } php-parser/lib/PhpParser/Builder/Interface_.php000064400000004673150250175720015453 0ustar00name = $name; } /** * Extends one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to extend * * @return $this The builder instance (for fluid interface) */ public function extend(...$interfaces) { foreach ($interfaces as $interface) { $this->extends[] = BuilderHelpers::normalizeName($interface); } return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof Stmt\ClassConst) { $this->constants[] = $stmt; } elseif ($stmt instanceof Stmt\ClassMethod) { // we erase all statements in the body of an interface method $stmt->stmts = null; $this->methods[] = $stmt; } else { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built interface node. * * @return Stmt\Interface_ The built interface node */ public function getNode() : PhpParser\Node { return new Stmt\Interface_($this->name, [ 'extends' => $this->extends, 'stmts' => array_merge($this->constants, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } php-parser/lib/PhpParser/Builder/Use_.php000064400000002304150250175720014274 0ustar00name = BuilderHelpers::normalizeName($name); $this->type = $type; } /** * Sets alias for used name. * * @param string $alias Alias to use (last component of full name by default) * * @return $this The builder instance (for fluid interface) */ public function as(string $alias) { $this->alias = $alias; return $this; } /** * Returns the built node. * * @return Stmt\Use_ The built node */ public function getNode() : Node { return new Stmt\Use_([ new Stmt\UseUse($this->name, $this->alias) ], $this->type); } } php-parser/lib/PhpParser/Builder/ClassConst.php000064400000006562150250175720015467 0ustar00constants = [new Const_($name, BuilderHelpers::normalizeValue($value))]; } /** * Add another constant to const group * * @param string|Identifier $name Name * @param Node\Expr|bool|null|int|float|string|array $value Value * * @return $this The builder instance (for fluid interface) */ public function addConst($name, $value) { $this->constants[] = new Const_($name, BuilderHelpers::normalizeValue($value)); return $this; } /** * Makes the constant public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Makes the constant protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Makes the constant private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Makes the constant final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); return $this; } /** * Sets doc comment for the constant. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = [ 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] ]; return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built class node. * * @return Stmt\ClassConst The built constant node */ public function getNode(): PhpParser\Node { return new Stmt\ClassConst( $this->constants, $this->flags, $this->attributes, $this->attributeGroups ); } } php-parser/lib/PhpParser/Parser.php000064400000001164150250175720013252 0ustar00= 7.0; for parsing PHP 5.2 to PHP 8.2). [Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2). Features -------- The main features provided by this library are: * Parsing PHP 5, PHP 7, and PHP 8 code into an abstract syntax tree (AST). * Invalid code can be parsed into a partial AST. * The AST contains accurate location information. * Dumping the AST in human-readable form. * Converting an AST back to PHP code. * Experimental: Formatting can be preserved for partially changed ASTs. * Infrastructure to traverse and modify ASTs. * Resolution of namespaced names. * Evaluation of constant expressions. * Builders to simplify AST construction for code generation. * Converting an AST into JSON and back. Quick Start ----------- Install the library using [composer](https://getcomposer.org): php composer.phar require nikic/php-parser Parse some PHP code into an AST and dump the result in human-readable form: ```php create(ParserFactory::PREFER_PHP7); try { $ast = $parser->parse($code); } catch (Error $error) { echo "Parse error: {$error->getMessage()}\n"; return; } $dumper = new NodeDumper; echo $dumper->dump($ast) . "\n"; ``` This dumps an AST looking something like this: ``` array( 0: Stmt_Function( byRef: false name: Identifier( name: test ) params: array( 0: Param( type: null byRef: false variadic: false var: Expr_Variable( name: foo ) default: null ) ) returnType: null stmts: array( 0: Stmt_Expression( expr: Expr_FuncCall( name: Name( parts: array( 0: var_dump ) ) args: array( 0: Arg( value: Expr_Variable( name: foo ) byRef: false unpack: false ) ) ) ) ) ) ) ``` Let's traverse the AST and perform some kind of modification. For example, drop all function bodies: ```php use PhpParser\Node; use PhpParser\Node\Stmt\Function_; use PhpParser\NodeTraverser; use PhpParser\NodeVisitorAbstract; $traverser = new NodeTraverser(); $traverser->addVisitor(new class extends NodeVisitorAbstract { public function enterNode(Node $node) { if ($node instanceof Function_) { // Clean out the function body $node->stmts = []; } } }); $ast = $traverser->traverse($ast); echo $dumper->dump($ast) . "\n"; ``` This gives us an AST where the `Function_::$stmts` are empty: ``` array( 0: Stmt_Function( byRef: false name: Identifier( name: test ) params: array( 0: Param( type: null byRef: false variadic: false var: Expr_Variable( name: foo ) default: null ) ) returnType: null stmts: array( ) ) ) ``` Finally, we can convert the new AST back to PHP code: ```php use PhpParser\PrettyPrinter; $prettyPrinter = new PrettyPrinter\Standard; echo $prettyPrinter->prettyPrintFile($ast); ``` This gives us our original code, minus the `var_dump()` call inside the function: ```php