| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 ASSERT(IsAccessorAccessorConflict(old_type, type)); | 118 ASSERT(IsAccessorAccessorConflict(old_type, type)); |
| 119 // Both accessors of the same type. | 119 // Both accessors of the same type. |
| 120 parser_->ReportMessageAt(scanner_->location(), | 120 parser_->ReportMessageAt(scanner_->location(), |
| 121 "accessor_get_set"); | 121 "accessor_get_set"); |
| 122 } | 122 } |
| 123 *ok = false; | 123 *ok = false; |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 | 126 |
| 127 | 127 |
| 128 // Common base class shared between parser and pre-parser. |
| 129 class ParserBase { |
| 130 public: |
| 131 ParserBase(Scanner* scanner, uintptr_t stack_limit) |
| 132 : scanner_(scanner), |
| 133 stack_limit_(stack_limit), |
| 134 stack_overflow_(false), |
| 135 allow_lazy_(false), |
| 136 allow_natives_syntax_(false), |
| 137 allow_generators_(false), |
| 138 allow_for_of_(false) { } |
| 139 // TODO(mstarzinger): Only virtual until message reporting has been unified. |
| 140 virtual ~ParserBase() { } |
| 141 |
| 142 // Getters that indicate whether certain syntactical constructs are |
| 143 // allowed to be parsed by this instance of the parser. |
| 144 bool allow_lazy() const { return allow_lazy_; } |
| 145 bool allow_natives_syntax() const { return allow_natives_syntax_; } |
| 146 bool allow_generators() const { return allow_generators_; } |
| 147 bool allow_for_of() const { return allow_for_of_; } |
| 148 bool allow_modules() const { return scanner()->HarmonyModules(); } |
| 149 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } |
| 150 bool allow_harmony_numeric_literals() const { |
| 151 return scanner()->HarmonyNumericLiterals(); |
| 152 } |
| 153 |
| 154 // Setters that determine whether certain syntactical constructs are |
| 155 // allowed to be parsed by this instance of the parser. |
| 156 void set_allow_lazy(bool allow) { allow_lazy_ = allow; } |
| 157 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; } |
| 158 void set_allow_generators(bool allow) { allow_generators_ = allow; } |
| 159 void set_allow_for_of(bool allow) { allow_for_of_ = allow; } |
| 160 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); } |
| 161 void set_allow_harmony_scoping(bool allow) { |
| 162 scanner()->SetHarmonyScoping(allow); |
| 163 } |
| 164 void set_allow_harmony_numeric_literals(bool allow) { |
| 165 scanner()->SetHarmonyNumericLiterals(allow); |
| 166 } |
| 167 |
| 168 protected: |
| 169 Scanner* scanner() const { return scanner_; } |
| 170 bool stack_overflow() const { return stack_overflow_; } |
| 171 void set_stack_overflow() { stack_overflow_ = true; } |
| 172 |
| 173 INLINE(Token::Value peek()) { |
| 174 if (stack_overflow_) return Token::ILLEGAL; |
| 175 return scanner()->peek(); |
| 176 } |
| 177 |
| 178 INLINE(Token::Value Next()) { |
| 179 if (stack_overflow_) return Token::ILLEGAL; |
| 180 { |
| 181 int marker; |
| 182 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) { |
| 183 // Any further calls to Next or peek will return the illegal token. |
| 184 // The current call must return the next token, which might already |
| 185 // have been peek'ed. |
| 186 stack_overflow_ = true; |
| 187 } |
| 188 } |
| 189 return scanner()->Next(); |
| 190 } |
| 191 |
| 192 void Consume(Token::Value token) { |
| 193 Token::Value next = Next(); |
| 194 USE(next); |
| 195 USE(token); |
| 196 ASSERT(next == token); |
| 197 } |
| 198 |
| 199 bool Check(Token::Value token) { |
| 200 Token::Value next = peek(); |
| 201 if (next == token) { |
| 202 Consume(next); |
| 203 return true; |
| 204 } |
| 205 return false; |
| 206 } |
| 207 |
| 208 void Expect(Token::Value token, bool* ok) { |
| 209 Token::Value next = Next(); |
| 210 if (next != token) { |
| 211 ReportUnexpectedToken(next); |
| 212 *ok = false; |
| 213 } |
| 214 } |
| 215 |
| 216 bool peek_any_identifier(); |
| 217 void ExpectSemicolon(bool* ok); |
| 218 |
| 219 // Report syntax errors. |
| 220 virtual void ReportUnexpectedToken(Token::Value token) = 0; |
| 221 |
| 222 private: |
| 223 Scanner* scanner_; |
| 224 uintptr_t stack_limit_; |
| 225 bool stack_overflow_; |
| 226 |
| 227 bool allow_lazy_; |
| 228 bool allow_natives_syntax_; |
| 229 bool allow_generators_; |
| 230 bool allow_for_of_; |
| 231 }; |
| 232 |
| 233 |
| 128 // Preparsing checks a JavaScript program and emits preparse-data that helps | 234 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 129 // a later parsing to be faster. | 235 // a later parsing to be faster. |
| 130 // See preparse-data-format.h for the data format. | 236 // See preparse-data-format.h for the data format. |
| 131 | 237 |
| 132 // The PreParser checks that the syntax follows the grammar for JavaScript, | 238 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 133 // and collects some information about the program along the way. | 239 // and collects some information about the program along the way. |
| 134 // The grammar check is only performed in order to understand the program | 240 // The grammar check is only performed in order to understand the program |
| 135 // sufficiently to deduce some information about it, that can be used | 241 // sufficiently to deduce some information about it, that can be used |
| 136 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 242 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 137 // rather it is to speed up properly written and correct programs. | 243 // rather it is to speed up properly written and correct programs. |
| 138 // That means that contextual checks (like a label being declared where | 244 // That means that contextual checks (like a label being declared where |
| 139 // it is used) are generally omitted. | 245 // it is used) are generally omitted. |
| 140 | 246 |
| 141 typedef uint8_t byte; | 247 typedef uint8_t byte; |
| 142 namespace i = v8::internal; | 248 namespace i = v8::internal; |
| 143 | 249 |
| 144 class PreParser { | 250 class PreParser : public ParserBase { |
| 145 public: | 251 public: |
| 146 enum PreParseResult { | 252 enum PreParseResult { |
| 147 kPreParseStackOverflow, | 253 kPreParseStackOverflow, |
| 148 kPreParseSuccess | 254 kPreParseSuccess |
| 149 }; | 255 }; |
| 150 | 256 |
| 151 | 257 |
| 152 PreParser(i::Scanner* scanner, | 258 PreParser(i::Scanner* scanner, |
| 153 i::ParserRecorder* log, | 259 i::ParserRecorder* log, |
| 154 uintptr_t stack_limit) | 260 uintptr_t stack_limit) |
| 155 : scanner_(scanner), | 261 : ParserBase(scanner, stack_limit), |
| 156 log_(log), | 262 log_(log), |
| 157 scope_(NULL), | 263 scope_(NULL), |
| 158 stack_limit_(stack_limit), | |
| 159 strict_mode_violation_location_(i::Scanner::Location::invalid()), | 264 strict_mode_violation_location_(i::Scanner::Location::invalid()), |
| 160 strict_mode_violation_type_(NULL), | 265 strict_mode_violation_type_(NULL), |
| 161 stack_overflow_(false), | |
| 162 allow_lazy_(false), | |
| 163 allow_natives_syntax_(false), | |
| 164 allow_generators_(false), | |
| 165 allow_for_of_(false), | |
| 166 parenthesized_function_(false) { } | 266 parenthesized_function_(false) { } |
| 167 | 267 |
| 168 ~PreParser() {} | 268 ~PreParser() {} |
| 169 | 269 |
| 170 bool allow_natives_syntax() const { return allow_natives_syntax_; } | |
| 171 bool allow_lazy() const { return allow_lazy_; } | |
| 172 bool allow_modules() const { return scanner_->HarmonyModules(); } | |
| 173 bool allow_harmony_scoping() const { return scanner_->HarmonyScoping(); } | |
| 174 bool allow_generators() const { return allow_generators_; } | |
| 175 bool allow_for_of() const { return allow_for_of_; } | |
| 176 bool allow_harmony_numeric_literals() const { | |
| 177 return scanner_->HarmonyNumericLiterals(); | |
| 178 } | |
| 179 | |
| 180 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; } | |
| 181 void set_allow_lazy(bool allow) { allow_lazy_ = allow; } | |
| 182 void set_allow_modules(bool allow) { scanner_->SetHarmonyModules(allow); } | |
| 183 void set_allow_harmony_scoping(bool allow) { | |
| 184 scanner_->SetHarmonyScoping(allow); | |
| 185 } | |
| 186 void set_allow_generators(bool allow) { allow_generators_ = allow; } | |
| 187 void set_allow_for_of(bool allow) { allow_for_of_ = allow; } | |
| 188 void set_allow_harmony_numeric_literals(bool allow) { | |
| 189 scanner_->SetHarmonyNumericLiterals(allow); | |
| 190 } | |
| 191 | |
| 192 // Pre-parse the program from the character stream; returns true on | 270 // Pre-parse the program from the character stream; returns true on |
| 193 // success (even if parsing failed, the pre-parse data successfully | 271 // success (even if parsing failed, the pre-parse data successfully |
| 194 // captured the syntax error), and false if a stack-overflow happened | 272 // captured the syntax error), and false if a stack-overflow happened |
| 195 // during parsing. | 273 // during parsing. |
| 196 PreParseResult PreParseProgram() { | 274 PreParseResult PreParseProgram() { |
| 197 Scope top_scope(&scope_, kTopLevelScope); | 275 Scope top_scope(&scope_, kTopLevelScope); |
| 198 bool ok = true; | 276 bool ok = true; |
| 199 int start_position = scanner_->peek_location().beg_pos; | 277 int start_position = scanner()->peek_location().beg_pos; |
| 200 ParseSourceElements(i::Token::EOS, &ok); | 278 ParseSourceElements(i::Token::EOS, &ok); |
| 201 if (stack_overflow_) return kPreParseStackOverflow; | 279 if (stack_overflow()) return kPreParseStackOverflow; |
| 202 if (!ok) { | 280 if (!ok) { |
| 203 ReportUnexpectedToken(scanner_->current_token()); | 281 ReportUnexpectedToken(scanner()->current_token()); |
| 204 } else if (!scope_->is_classic_mode()) { | 282 } else if (!scope_->is_classic_mode()) { |
| 205 CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok); | 283 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); |
| 206 } | 284 } |
| 207 return kPreParseSuccess; | 285 return kPreParseSuccess; |
| 208 } | 286 } |
| 209 | 287 |
| 210 // Parses a single function literal, from the opening parentheses before | 288 // Parses a single function literal, from the opening parentheses before |
| 211 // parameters to the closing brace after the body. | 289 // parameters to the closing brace after the body. |
| 212 // Returns a FunctionEntry describing the body of the function in enough | 290 // Returns a FunctionEntry describing the body of the function in enough |
| 213 // detail that it can be lazily compiled. | 291 // detail that it can be lazily compiled. |
| 214 // The scanner is expected to have matched the "function" or "function*" | 292 // The scanner is expected to have matched the "function" or "function*" |
| 215 // keyword and parameters, and have consumed the initial '{'. | 293 // keyword and parameters, and have consumed the initial '{'. |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 bool* is_set, | 675 bool* is_set, |
| 598 bool* ok); | 676 bool* ok); |
| 599 | 677 |
| 600 // Logs the currently parsed literal as a symbol in the preparser data. | 678 // Logs the currently parsed literal as a symbol in the preparser data. |
| 601 void LogSymbol(); | 679 void LogSymbol(); |
| 602 // Log the currently parsed identifier. | 680 // Log the currently parsed identifier. |
| 603 Identifier GetIdentifierSymbol(); | 681 Identifier GetIdentifierSymbol(); |
| 604 // Log the currently parsed string literal. | 682 // Log the currently parsed string literal. |
| 605 Expression GetStringSymbol(); | 683 Expression GetStringSymbol(); |
| 606 | 684 |
| 607 i::Token::Value peek() { | |
| 608 if (stack_overflow_) return i::Token::ILLEGAL; | |
| 609 return scanner_->peek(); | |
| 610 } | |
| 611 | |
| 612 i::Token::Value Next() { | |
| 613 if (stack_overflow_) return i::Token::ILLEGAL; | |
| 614 { | |
| 615 int marker; | |
| 616 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) { | |
| 617 // Further calls to peek/Next will return illegal token. | |
| 618 // The current one will still be returned. It might already | |
| 619 // have been seen using peek. | |
| 620 stack_overflow_ = true; | |
| 621 } | |
| 622 } | |
| 623 return scanner_->Next(); | |
| 624 } | |
| 625 | |
| 626 bool peek_any_identifier(); | |
| 627 | |
| 628 void set_language_mode(i::LanguageMode language_mode) { | 685 void set_language_mode(i::LanguageMode language_mode) { |
| 629 scope_->set_language_mode(language_mode); | 686 scope_->set_language_mode(language_mode); |
| 630 } | 687 } |
| 631 | 688 |
| 632 bool is_classic_mode() { | 689 bool is_classic_mode() { |
| 633 return scope_->language_mode() == i::CLASSIC_MODE; | 690 return scope_->language_mode() == i::CLASSIC_MODE; |
| 634 } | 691 } |
| 635 | 692 |
| 636 bool is_extended_mode() { | 693 bool is_extended_mode() { |
| 637 return scope_->language_mode() == i::EXTENDED_MODE; | 694 return scope_->language_mode() == i::EXTENDED_MODE; |
| 638 } | 695 } |
| 639 | 696 |
| 640 i::LanguageMode language_mode() { return scope_->language_mode(); } | 697 i::LanguageMode language_mode() { return scope_->language_mode(); } |
| 641 | 698 |
| 642 void Consume(i::Token::Value token) { Next(); } | |
| 643 | |
| 644 void Expect(i::Token::Value token, bool* ok) { | |
| 645 if (Next() != token) { | |
| 646 *ok = false; | |
| 647 } | |
| 648 } | |
| 649 | |
| 650 bool Check(i::Token::Value token) { | |
| 651 i::Token::Value next = peek(); | |
| 652 if (next == token) { | |
| 653 Consume(next); | |
| 654 return true; | |
| 655 } | |
| 656 return false; | |
| 657 } | |
| 658 void ExpectSemicolon(bool* ok); | |
| 659 | |
| 660 bool CheckInOrOf(bool accept_OF); | 699 bool CheckInOrOf(bool accept_OF); |
| 661 | 700 |
| 662 static int Precedence(i::Token::Value tok, bool accept_IN); | 701 static int Precedence(i::Token::Value tok, bool accept_IN); |
| 663 | 702 |
| 664 void SetStrictModeViolation(i::Scanner::Location, | 703 void SetStrictModeViolation(i::Scanner::Location, |
| 665 const char* type, | 704 const char* type, |
| 666 bool* ok); | 705 bool* ok); |
| 667 | 706 |
| 668 void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); | 707 void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); |
| 669 | 708 |
| 670 void StrictModeIdentifierViolation(i::Scanner::Location, | 709 void StrictModeIdentifierViolation(i::Scanner::Location, |
| 671 const char* eval_args_type, | 710 const char* eval_args_type, |
| 672 Identifier identifier, | 711 Identifier identifier, |
| 673 bool* ok); | 712 bool* ok); |
| 674 | 713 |
| 675 i::Scanner* scanner_; | |
| 676 i::ParserRecorder* log_; | 714 i::ParserRecorder* log_; |
| 677 Scope* scope_; | 715 Scope* scope_; |
| 678 uintptr_t stack_limit_; | |
| 679 i::Scanner::Location strict_mode_violation_location_; | 716 i::Scanner::Location strict_mode_violation_location_; |
| 680 const char* strict_mode_violation_type_; | 717 const char* strict_mode_violation_type_; |
| 681 bool stack_overflow_; | |
| 682 bool allow_lazy_; | |
| 683 bool allow_natives_syntax_; | |
| 684 bool allow_generators_; | |
| 685 bool allow_for_of_; | |
| 686 bool parenthesized_function_; | 718 bool parenthesized_function_; |
| 687 | 719 |
| 688 friend class i::ObjectLiteralChecker<PreParser>; | 720 friend class i::ObjectLiteralChecker<PreParser>; |
| 689 }; | 721 }; |
| 690 | 722 |
| 691 } } // v8::internal | 723 } } // v8::internal |
| 692 | 724 |
| 693 #endif // V8_PREPARSER_H | 725 #endif // V8_PREPARSER_H |
| OLD | NEW |