diff --git a/support/xhpast/ast.hpp b/support/xhpast/ast.hpp --- a/support/xhpast/ast.hpp +++ b/support/xhpast/ast.hpp @@ -10,14 +10,21 @@ class yy_extra_type { public: yy_extra_type() { + first_lineno = 0; lineno = 1; terminated = false; used = false; + last_token = -1; + insert_token = -1; + heredoc_yyleng = -1; + heredoc_data = (char *) 0; short_tags = true; asp_tags = false; idx_expr = false; include_debug = false; expecting_xhp_class_statements = false; + old_expecting_xhp_class_statements = false; + used_attributes = false; list_size = 0; colon_hack = false; pushStack(); @@ -26,7 +33,6 @@ bool short_tags; // `short_open_tag` in php.ini bool asp_tags; // `asp_tags` in php.ini bool idx_expr; // allow code like `foo()['bar']` - bool include_debug; // include line numbers and file names in XHP object creation size_t first_lineno; // line number before scanning the current token size_t lineno; // current line number being scanned. std::string error; // description of error (if terminated true) @@ -34,16 +40,21 @@ bool used; // were any XHP-specific extensions found in this code? int last_token; // the last token to be returned by the scanner int insert_token; // insert this token without reading from buffer - size_t heredoc_yyleng; // last length of yytext while scannling + size_t heredoc_yyleng; // last length of yytext while scanning const char* heredoc_data; // where our heredoc data starts std::string heredoc_label; // heredoc sentinel label std::stack curly_stack; // tokens appearing before a { bool expecting_xhp_class_statements; // when we're one level deep in a class - bool old_expecting_xhp_class_statements; // store old value while inside class method bool used_attributes; // did this class use the `attribute` keyword unsigned int list_size; bool colon_hack; + // Include line numbers and file names in XHP object creation. + bool include_debug; + + // Store old value while inside class method. + bool old_expecting_xhp_class_statements; + xhpast::token_list_t token_list; /* Utility functions for checking proper tag closing */ diff --git a/support/xhpast/astnode.hpp b/support/xhpast/astnode.hpp --- a/support/xhpast/astnode.hpp +++ b/support/xhpast/astnode.hpp @@ -20,6 +20,7 @@ Token(unsigned int type, char *value, unsigned int n) : type(type), value(value), + lineno(0), n(n) { } }; @@ -60,7 +61,10 @@ } Node *appendChildren(Node *node) { - for (node_list_t::iterator ii = node->children.begin(); ii != node->children.end(); ++ii) { + for (node_list_t::iterator ii = node->children.begin(); + ii != node->children.end(); + ++ii) { + this->appendChild(*ii); } return this; @@ -80,7 +84,10 @@ Node *expandRange(Node *n) { if (!n) { - fprintf(stderr, "Trying to expandRange() a null node to one of type %d\n", this->type); + fprintf( + stderr, + "Trying to expandRange() a null node to one of type %d\n", + this->type); exit(1); }; diff --git a/support/xhpast/parser.y b/support/xhpast/parser.y --- a/support/xhpast/parser.y +++ b/support/xhpast/parser.y @@ -82,7 +82,17 @@ %left T_LOGICAL_XOR %left T_LOGICAL_AND %right T_PRINT -%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 +%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 %left '?' ':' %left T_BOOLEAN_OR %left T_BOOLEAN_AND @@ -96,7 +106,18 @@ %left '*' '/' '%' %right '!' %nonassoc T_INSTANCEOF -%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_UNICODE_CAST T_BINARY_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' +%right '~' T_INC + T_DEC + T_INT_CAST + T_DOUBLE_CAST + T_STRING_CAST + T_UNICODE_CAST + T_BINARY_CAST + T_ARRAY_CAST + T_OBJECT_CAST + T_BOOL_CAST + T_UNSET_CAST + '@' %right '[' %nonassoc T_NEW T_CLONE %token T_EXIT @@ -115,7 +136,8 @@ %token T_CHARACTER /* unused in vanilla PHP */ %token T_BAD_CHARACTER /* unused in vanilla PHP */ %token T_ENCAPSED_AND_WHITESPACE /* unused in XHP: ` ` in `" "` */ -%token T_CONSTANT_ENCAPSED_STRING /* overloaded in XHP; replaces '"' encaps_list '"' */ +%token T_CONSTANT_ENCAPSED_STRING /* overloaded in XHP; + replaces '"' encaps_list '"' */ %token T_BACKTICKS_EXPR /* new in XHP; replaces '`' backticks_expr '`' */ %token T_ECHO %token T_DO @@ -171,7 +193,8 @@ %token T_WHITESPACE %token T_START_HEREDOC /* unused in XHP; replaced with T_HEREDOC */ %token T_END_HEREDOC /* unused in XHP; replaced with T_HEREDOC */ -%token T_HEREDOC /* new in XHP; replaces start_heredoc encaps_list T_END_HEREDOC */ +%token T_HEREDOC /* new in XHP; + replaces start_heredoc encaps_list T_END_HEREDOC */ %token T_DOLLAR_OPEN_CURLY_BRACES /* unused in XHP: `${` in `"${foo}"` */ %token T_CURLY_OPEN /* unused in XHP: `{$` in `"{$foo}"` */ %token T_PAAMAYIM_NEKUDOTAYIM @@ -383,7 +406,11 @@ $$ = NNEW(n_STATEMENT)->appendChild($$); } -| T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { +| T_IF '(' expr ')' ':' + inner_statement_list + new_elseif_list + new_else_single + T_ENDIF ';' { $$ = NNEW(n_CONDITION_LIST); NTYPE($1, n_IF); @@ -515,7 +542,8 @@ $$ = NNEW(n_STATEMENT)->appendChild($3); NMORE($$, $5); } -| T_FOREACH '(' variable T_AS foreach_variable foreach_optional_arg ')' foreach_statement { +| T_FOREACH '(' variable T_AS foreach_variable foreach_optional_arg ')' + foreach_statement { NTYPE($1, n_FOREACH); NSPAN($2, n_FOREACH_EXPRESSION, $7); $2->appendChild($3); @@ -532,7 +560,8 @@ $$ = NNEW(n_STATEMENT)->appendChild($1); } -| T_FOREACH '(' expr_without_variable T_AS variable foreach_optional_arg ')' foreach_statement { +| T_FOREACH '(' expr_without_variable T_AS variable foreach_optional_arg ')' + foreach_statement { NTYPE($1, n_FOREACH); NSPAN($2, n_FOREACH_EXPRESSION, $7); $2->appendChild($3); @@ -558,7 +587,11 @@ $$ = NNEW(n_STATEMENT)->appendChild(NNEW(n_EMPTY)); NMORE($$, $1); } -| T_TRY '{' inner_statement_list '}' T_CATCH '(' fully_qualified_class_name T_VARIABLE ')' '{' inner_statement_list '}' additional_catches finally_statement { +| T_TRY '{' inner_statement_list '}' + T_CATCH '(' fully_qualified_class_name T_VARIABLE ')' + '{' inner_statement_list '}' + additional_catches + finally_statement { NTYPE($1, n_TRY); $1->appendChild(NEXPAND($2, $3, $4)); @@ -622,7 +655,8 @@ ; additional_catch: - T_CATCH '(' fully_qualified_class_name T_VARIABLE ')' '{' inner_statement_list '}' { + T_CATCH '(' fully_qualified_class_name T_VARIABLE ')' + '{' inner_statement_list '}' { NTYPE($1, n_CATCH); $1->appendChild($3); $1->appendChild(NTYPE($4, n_VARIABLE)); @@ -665,7 +699,8 @@ ; unticked_function_declaration_statement: - function is_reference T_STRING '(' parameter_list ')' '{' inner_statement_list '}' { + function is_reference T_STRING + '(' parameter_list ')' '{' inner_statement_list '}' { NSPAN($1, n_FUNCTION_DECLARATION, $9); $1->appendChild(NNEW(n_EMPTY)); $1->appendChild($2); @@ -679,7 +714,8 @@ ; unticked_class_declaration_statement: - class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}' { + class_entry_type T_STRING extends_from implements_list + '{' class_statement_list '}' { $$ = NNEW(n_CLASS_DECLARATION); $$->appendChild($1); $$->appendChild(NTYPE($2, n_CLASS_NAME)); @@ -1007,7 +1043,8 @@ $$ = $1->appendChild($$); } -| non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' static_scalar { +| non_empty_parameter_list ',' optional_class_type '&' + T_VARIABLE '=' static_scalar { $$ = NNEW(n_DECLARATION_PARAMETER); $$->appendChild($3); $$->appendChild(NTYPE($4, n_VARIABLE_REFERENCE)); @@ -1016,7 +1053,8 @@ $$ = $1->appendChild($$); } -| non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar { +| non_empty_parameter_list ',' optional_class_type + T_VARIABLE '=' static_scalar { $$ = NNEW(n_DECLARATION_PARAMETER); $$->appendChild($3); $$->appendChild(NTYPE($4, n_VARIABLE)); @@ -1159,10 +1197,12 @@ $$ = $1; } | method_modifiers function { - yyextra->old_expecting_xhp_class_statements = yyextra->expecting_xhp_class_statements; + yyextra->old_expecting_xhp_class_statements = + yyextra->expecting_xhp_class_statements; yyextra->expecting_xhp_class_statements = false; } is_reference T_STRING '(' parameter_list ')' method_body { - yyextra->expecting_xhp_class_statements = yyextra->old_expecting_xhp_class_statements; + yyextra->expecting_xhp_class_statements = + yyextra->old_expecting_xhp_class_statements; $$ = NNEW(n_METHOD_DECLARATION); NMORE($$, $2); @@ -1819,7 +1859,10 @@ $1->appendChild(NNEW(n_EMPTY)); $$ = $1; } -| function is_reference '(' parameter_list ')' lexical_vars '{' inner_statement_list '}' { +| function is_reference + '(' parameter_list ')' + lexical_vars + '{' inner_statement_list '}' { NSPAN($1, n_FUNCTION_DECLARATION, $9); $1->appendChild(NNEW(n_EMPTY)); $1->appendChild($2); @@ -1830,7 +1873,10 @@ $$ = $1; } -| T_STATIC function is_reference '(' parameter_list ')' lexical_vars '{' inner_statement_list '}' { +| T_STATIC function is_reference + '(' parameter_list ')' + lexical_vars + '{' inner_statement_list '}' { NSPAN($2, n_FUNCTION_DECLARATION, $10); NMORE($2, $1); @@ -1918,7 +1964,8 @@ $$->appendChild($1); $$->appendChild(NEXPAND($2, $3, $4)); } -| T_NAMESPACE T_NS_SEPARATOR namespace_name '(' function_call_parameter_list ')' { +| T_NAMESPACE T_NS_SEPARATOR namespace_name + '(' function_call_parameter_list ')' { NMORE($3, $1); $$ = NNEW(n_FUNCTION_CALL); $$->appendChild($3); @@ -1930,7 +1977,8 @@ $$->appendChild($2); $$->appendChild(NEXPAND($3, $4, $5)); } -| class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' function_call_parameter_list ')' { +| class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING + '(' function_call_parameter_list ')' { $$ = NNEW(n_CLASS_STATIC_ACCESS); $$->appendChild($1); $$->appendChild(NTYPE($3, n_STRING)); @@ -1938,7 +1986,8 @@ $$ = NNEW(n_FUNCTION_CALL)->appendChild($$); $$->appendChild(NEXPAND($4, $5, $6)); } -| variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' function_call_parameter_list ')' { +| variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING + '(' function_call_parameter_list ')' { $$ = NNEW(n_CLASS_STATIC_ACCESS); $$->appendChild($1); $$->appendChild(NTYPE($3, n_STRING)); @@ -1946,7 +1995,8 @@ $$ = NNEW(n_FUNCTION_CALL)->appendChild($$); $$->appendChild(NEXPAND($4, $5, $6)); } -| variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' function_call_parameter_list ')' { +| variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects + '(' function_call_parameter_list ')' { $$ = NNEW(n_CLASS_STATIC_ACCESS); $$->appendChild($1); $$->appendChild(NTYPE($3, n_STRING)); @@ -1954,7 +2004,8 @@ $$ = NNEW(n_FUNCTION_CALL)->appendChild($$); $$->appendChild(NEXPAND($4, $5, $6)); } -| class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' function_call_parameter_list ')' { +| class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects + '(' function_call_parameter_list ')' { $$ = NNEW(n_CLASS_STATIC_ACCESS); $$->appendChild($1); $$->appendChild(NTYPE($3, n_STRING)); @@ -2006,11 +2057,17 @@ ; dynamic_class_name_reference: - base_variable T_OBJECT_OPERATOR object_property dynamic_class_name_variable_properties { + base_variable + T_OBJECT_OPERATOR + object_property + dynamic_class_name_variable_properties { $$ = NNEW(n_OBJECT_PROPERTY_ACCESS); $$->appendChild($1); $$->appendChild($3); - for (xhpast::node_list_t::iterator ii = $4->children.begin(); ii != $4->children.end(); ++ii) { + for (xhpast::node_list_t::iterator ii = $4->children.begin(); + ii != $4->children.end(); + ++ii) { + $$ = NNEW(n_OBJECT_PROPERTY_ACCESS)->appendChild($$); $$->appendChild(*ii); } @@ -2170,7 +2227,11 @@ ; non_empty_static_array_pair_list: - non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW static_scalar { + non_empty_static_array_pair_list + ',' + static_scalar + T_DOUBLE_ARROW + static_scalar { $$ = NNEW(n_ARRAY_VALUE); $$->appendChild($3); $$->appendChild($5); @@ -2218,7 +2279,10 @@ ; variable: - base_variable_with_function_calls T_OBJECT_OPERATOR object_property method_or_not variable_properties { + base_variable_with_function_calls + T_OBJECT_OPERATOR + object_property method_or_not + variable_properties { $$ = NNEW(n_OBJECT_PROPERTY_ACCESS); $$->appendChild($1); $$->appendChild($3); @@ -2228,7 +2292,10 @@ $$->appendChild($4); } - for (xhpast::node_list_t::iterator ii = $5->children.begin(); ii != $5->children.end(); ++ii) { + for (xhpast::node_list_t::iterator ii = $5->children.begin(); + ii != $5->children.end(); + ++ii) { + if ((*ii)->type == n_CALL_PARAMETER_LIST) { $$ = NNEW(n_METHOD_CALL)->appendChild($$); $$->appendChild((*ii)); diff --git a/support/xhpast/scanner.l b/support/xhpast/scanner.l --- a/support/xhpast/scanner.l +++ b/support/xhpast/scanner.l @@ -9,7 +9,8 @@ if (!yyg->yy_more_len) \ yyextra->first_lineno = yyextra->lineno; #define pttok(t, txt) \ - yyextra->token_list.push_back(new xhpast::Token(t, txt, yyextra->list_size++)); \ + yyextra->token_list.push_back( \ + new xhpast::Token(t, txt, yyextra->list_size++)); \ *yylval = new xhpast::Node(0, yyextra->list_size - 1); #define ptok(t) \ pttok(t, yytext); @@ -303,7 +304,8 @@ /* Casts */ { "("{TABS_AND_SPACES}(int|integer){TABS_AND_SPACES}")" tok(T_INT_CAST); - "("{TABS_AND_SPACES}(real|double|float){TABS_AND_SPACES}")" tok(T_DOUBLE_CAST); + "("{TABS_AND_SPACES}(real|double|float){TABS_AND_SPACES}")" + tok(T_DOUBLE_CAST); "("{TABS_AND_SPACES}(string|binary){TABS_AND_SPACES}")" tok(T_STRING_CAST); "("{TABS_AND_SPACES}array{TABS_AND_SPACES}")" tok(T_ARRAY_CAST); "("{TABS_AND_SPACES}object{TABS_AND_SPACES}")" tok(T_OBJECT_CAST); @@ -311,7 +313,8 @@ "("{TABS_AND_SPACES}unset{TABS_AND_SPACES}")" tok(T_UNSET_CAST); } - /* Scalars (parsing these doesn't really matter since we just pass them through literally) */ +// Scalars (parsing these doesn't really matter since we just pass +// them through literally) { {LNUM}|{HNUM}|{BNUM} tok(T_LNUMBER); {DNUM}|{EXPONENT_DNUM} tok(T_DNUMBER); @@ -328,7 +331,9 @@ } /* (HERE|NOW)DOC's */ -b?"<<<"{TABS_AND_SPACES} { +b?"<<< + "{TABS_AND_SPACES} { + push_state(PHP_HEREDOC_START); yyextra->heredoc_yyleng = yyleng; yymore(); @@ -339,7 +344,9 @@ // yytext will actually start at the "<<<" and not the label. Use of // heredoc_yyleng jumps past that. Then we add 1 to get past the " or '. The // match is similar to calculate length. - yyextra->heredoc_label = string(yytext + yyextra->heredoc_yyleng + 1, yyleng - yyextra->heredoc_yyleng - 2); + yyextra->heredoc_label = string( + yytext + yyextra->heredoc_yyleng + 1, + yyleng - yyextra->heredoc_yyleng - 2); set_state(PHP_HEREDOC_NSTART); yyextra->heredoc_yyleng = yyleng; yymore(); @@ -358,10 +365,17 @@ } { {LABEL};?{NEWLINE} { - if (strncmp(yyextra->heredoc_label.c_str(), yytext + yyextra->heredoc_yyleng, yyextra->heredoc_label.size()) == 0) { + if (strncmp( + yyextra->heredoc_label.c_str(), + yytext + yyextra->heredoc_yyleng, yyextra->heredoc_label.size()) == 0) { + switch (yytext[yyextra->heredoc_yyleng + yyextra->heredoc_label.size()]) { case ';': case '\n': case '\r': - yyless(yyleng - (yyleng - yyextra->heredoc_yyleng - yyextra->heredoc_label.size())); + yyless( + yyleng - ( + yyleng - + yyextra->heredoc_yyleng - + yyextra->heredoc_label.size())); pop_state(); tok(T_HEREDOC); } @@ -491,7 +505,11 @@ void xhp_new_push_state(int s, struct yyguts_t* yyg) { #ifdef DEBUG - fprintf(stderr, "--> PUSH(%s -> %s)\n", yy_state_name(YY_START), yy_state_name(s)); + fprintf( + stderr, + "--> PUSH(%s -> %s)\n", + yy_state_name(YY_START), + yy_state_name(s)); #endif yy_push_state(s, yyg); } @@ -502,7 +520,11 @@ #endif yy_pop_state(yyg); #ifdef DEBUG - fprintf(stderr, "--> POP(%s -> %s)\n", yy_state_name(s), yy_state_name(YY_START)); + fprintf( + stderr, + "--> POP(%s -> %s)\n", + yy_state_name(s), + yy_state_name(YY_START)); #endif } diff --git a/support/xhpast/xhpast.cpp b/support/xhpast/xhpast.cpp --- a/support/xhpast/xhpast.cpp +++ b/support/xhpast/xhpast.cpp @@ -12,10 +12,8 @@ void print_node(xhpast::Node *node); int main(int argc, char* argv[]) { - vector files; - if (argc != 1) { - //coupling: modify also libphutil/src/parser/xhpast/bin/PhutilXHPASTBinary.php + // Coupling: modify also src/parser/xhpast/bin/PhutilXHPASTBinary.php cout << "5.5.8/1h\n"; return 0; } @@ -98,19 +96,20 @@ void print_node(xhpast::Node *node) { int l = -1; - int r = -1; if (node->l_tok != -1) { l = node->l_tok; } if (l == -1) { - printf("[%d]", node->type); + printf("[%u]", node->type); } else { + int r = -1; + if (node->r_tok != -1) { r = node->r_tok; } - printf("[%d, %d, %d", node->type, l, r); + printf("[%u, %d, %d", node->type, l, r); if (!node->children.empty()) { printf(", ["); for (xhpast::node_list_t::iterator ii = node->children.begin();;) {