Chromium Code Reviews| 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 11 matching lines...) Expand all Loading... | |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_PREPARSER_H | 28 #ifndef V8_PREPARSER_H |
| 29 #define V8_PREPARSER_H | 29 #define V8_PREPARSER_H |
| 30 | 30 |
| 31 #include "hashmap.h" | 31 #include "hashmap.h" |
| 32 #include "scopes.h" | |
| 32 #include "token.h" | 33 #include "token.h" |
| 33 #include "scanner.h" | 34 #include "scanner.h" |
| 34 | 35 |
| 35 namespace v8 { | 36 namespace v8 { |
| 36 namespace internal { | 37 namespace internal { |
| 37 | 38 |
| 38 // Common base class shared between parser and pre-parser. | 39 // Common base class shared between parser and pre-parser. |
| 39 template <typename Traits> | 40 template <typename Traits> |
| 40 class ParserBase : public Traits { | 41 class ParserBase : public Traits { |
| 41 public: | 42 public: |
| 42 ParserBase(Scanner* scanner, uintptr_t stack_limit, | 43 ParserBase(Scanner* scanner, uintptr_t stack_limit, |
| 43 typename Traits::ParserType this_object) | 44 typename Traits::ParserType this_object) |
| 44 : Traits(this_object), | 45 : Traits(this_object), |
| 45 parenthesized_function_(false), | 46 parenthesized_function_(false), |
| 47 scope_(NULL), | |
| 48 function_state_(NULL), | |
| 46 scanner_(scanner), | 49 scanner_(scanner), |
| 47 stack_limit_(stack_limit), | 50 stack_limit_(stack_limit), |
| 48 stack_overflow_(false), | 51 stack_overflow_(false), |
| 49 allow_lazy_(false), | 52 allow_lazy_(false), |
| 50 allow_natives_syntax_(false), | 53 allow_natives_syntax_(false), |
| 51 allow_generators_(false), | 54 allow_generators_(false), |
| 52 allow_for_of_(false) { } | 55 allow_for_of_(false) { } |
| 53 | 56 |
| 54 // Getters that indicate whether certain syntactical constructs are | 57 // Getters that indicate whether certain syntactical constructs are |
| 55 // allowed to be parsed by this instance of the parser. | 58 // allowed to be parsed by this instance of the parser. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 76 void set_allow_harmony_numeric_literals(bool allow) { | 79 void set_allow_harmony_numeric_literals(bool allow) { |
| 77 scanner()->SetHarmonyNumericLiterals(allow); | 80 scanner()->SetHarmonyNumericLiterals(allow); |
| 78 } | 81 } |
| 79 | 82 |
| 80 protected: | 83 protected: |
| 81 enum AllowEvalOrArgumentsAsIdentifier { | 84 enum AllowEvalOrArgumentsAsIdentifier { |
| 82 kAllowEvalOrArguments, | 85 kAllowEvalOrArguments, |
| 83 kDontAllowEvalOrArguments | 86 kDontAllowEvalOrArguments |
| 84 }; | 87 }; |
| 85 | 88 |
| 89 // --------------------------------------------------------------------------- | |
| 90 // FunctionState and BlockState together implement the parser's scope stack. | |
| 91 // The parser's current scope is in scope_. BlockState and FunctionState | |
| 92 // constructors push on the scope stack and the destructors pop. They are also | |
| 93 // used to hold the parser's per-function and per-block state. | |
| 94 class BlockState BASE_EMBEDDED { | |
| 95 public: | |
| 96 BlockState(typename Traits::ScopeClass** scope_stack, | |
| 97 typename Traits::ScopeClass* scope) | |
| 98 : scope_stack_(scope_stack), | |
| 99 outer_scope_(*scope_stack), | |
| 100 scope_(scope) { | |
| 101 *scope_stack_ = scope_; | |
| 102 } | |
| 103 ~BlockState() { *scope_stack_ = outer_scope_; } | |
| 104 | |
| 105 private: | |
| 106 typename Traits::ScopeClass** scope_stack_; | |
| 107 typename Traits::ScopeClass* outer_scope_; | |
| 108 typename Traits::ScopeClass* scope_; | |
| 109 }; | |
| 110 | |
| 111 class FunctionState BASE_EMBEDDED { | |
| 112 public: | |
| 113 FunctionState(FunctionState** function_state_stack, | |
| 114 typename Traits::ScopeClass** scope_stack, | |
| 115 typename Traits::ScopeClass* scope, | |
| 116 typename Traits::FunctionStateParamType* extra_param = NULL); | |
|
ulan
2014/02/13 10:43:27
Maybe rename Traits::FunctionStateParamType to jus
marja
2014/02/13 15:57:51
Done.
| |
| 117 ~FunctionState(); | |
| 118 | |
| 119 int NextMaterializedLiteralIndex() { | |
| 120 return next_materialized_literal_index_++; | |
| 121 } | |
| 122 int materialized_literal_count() { | |
| 123 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize; | |
| 124 } | |
| 125 | |
| 126 int NextHandlerIndex() { return next_handler_index_++; } | |
| 127 int handler_count() { return next_handler_index_; } | |
| 128 | |
| 129 void AddProperty() { expected_property_count_++; } | |
| 130 int expected_property_count() { return expected_property_count_; } | |
| 131 | |
| 132 void set_is_generator(bool is_generator) { is_generator_ = is_generator; } | |
| 133 bool is_generator() const { return is_generator_; } | |
| 134 | |
| 135 void set_generator_object_variable( | |
| 136 typename Traits::GeneratorVariableType* variable) { | |
| 137 ASSERT(variable != NULL); | |
| 138 ASSERT(!is_generator()); | |
| 139 generator_object_variable_ = variable; | |
| 140 is_generator_ = true; | |
| 141 } | |
| 142 typename Traits::GeneratorVariableType* generator_object_variable() const { | |
| 143 return generator_object_variable_; | |
| 144 } | |
| 145 | |
| 146 typename Traits::FactoryType* factory() { return &factory_; } | |
| 147 | |
| 148 private: | |
| 149 // Used to assign an index to each literal that needs materialization in | |
| 150 // the function. Includes regexp literals, and boilerplate for object and | |
| 151 // array literals. | |
| 152 int next_materialized_literal_index_; | |
| 153 | |
| 154 // Used to assign a per-function index to try and catch handlers. | |
| 155 int next_handler_index_; | |
| 156 | |
| 157 // Properties count estimation. | |
| 158 int expected_property_count_; | |
| 159 | |
| 160 // Whether the function is a generator. | |
| 161 bool is_generator_; | |
| 162 // For generators, this variable may hold the generator object. It variable | |
| 163 // is used by yield expressions and return statements. It is not necessary | |
| 164 // for generator functions to have this variable set. | |
| 165 Variable* generator_object_variable_; | |
| 166 | |
| 167 FunctionState** function_state_stack_; | |
| 168 FunctionState* outer_function_state_; | |
| 169 typename Traits::ScopeClass** scope_stack_; | |
| 170 typename Traits::ScopeClass* outer_scope_; | |
| 171 Isolate* isolate_; // Only used by ParserTraits. | |
| 172 int saved_ast_node_id_; // Only used by ParserTraits. | |
| 173 typename Traits::FactoryType factory_; | |
| 174 | |
| 175 friend class ParserTraits; | |
| 176 }; | |
| 177 | |
| 86 Scanner* scanner() const { return scanner_; } | 178 Scanner* scanner() const { return scanner_; } |
| 87 int position() { return scanner_->location().beg_pos; } | 179 int position() { return scanner_->location().beg_pos; } |
| 88 int peek_position() { return scanner_->peek_location().beg_pos; } | 180 int peek_position() { return scanner_->peek_location().beg_pos; } |
| 89 bool stack_overflow() const { return stack_overflow_; } | 181 bool stack_overflow() const { return stack_overflow_; } |
| 90 void set_stack_overflow() { stack_overflow_ = true; } | 182 void set_stack_overflow() { stack_overflow_ = true; } |
| 91 | 183 |
| 92 INLINE(Token::Value peek()) { | 184 INLINE(Token::Value peek()) { |
| 93 if (stack_overflow_) return Token::ILLEGAL; | 185 if (stack_overflow_) return Token::ILLEGAL; |
| 94 return scanner()->peek(); | 186 return scanner()->peek(); |
| 95 } | 187 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 } | 278 } |
| 187 } | 279 } |
| 188 | 280 |
| 189 // Determine precedence of given token. | 281 // Determine precedence of given token. |
| 190 static int Precedence(Token::Value token, bool accept_IN) { | 282 static int Precedence(Token::Value token, bool accept_IN) { |
| 191 if (token == Token::IN && !accept_IN) | 283 if (token == Token::IN && !accept_IN) |
| 192 return 0; // 0 precedence will terminate binary expression parsing | 284 return 0; // 0 precedence will terminate binary expression parsing |
| 193 return Token::Precedence(token); | 285 return Token::Precedence(token); |
| 194 } | 286 } |
| 195 | 287 |
| 288 typename Traits::FactoryType* factory() { return function_state_->factory(); } | |
| 289 | |
| 290 bool is_classic_mode() const { return scope_->is_classic_mode(); } | |
| 291 | |
| 292 bool is_generator() const { return function_state_->is_generator(); } | |
| 293 | |
| 196 // Report syntax errors. | 294 // Report syntax errors. |
| 197 void ReportMessage(const char* message, Vector<const char*> args) { | 295 void ReportMessage(const char* message, Vector<const char*> args) { |
| 198 Scanner::Location source_location = scanner()->location(); | 296 Scanner::Location source_location = scanner()->location(); |
| 199 Traits::ReportMessageAt(source_location, message, args); | 297 Traits::ReportMessageAt(source_location, message, args); |
| 200 } | 298 } |
| 201 | 299 |
| 202 void ReportMessageAt(Scanner::Location location, const char* message) { | 300 void ReportMessageAt(Scanner::Location location, const char* message) { |
| 203 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); | 301 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); |
| 204 } | 302 } |
| 205 | 303 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 DuplicateFinder finder_; | 379 DuplicateFinder finder_; |
| 282 LanguageMode language_mode_; | 380 LanguageMode language_mode_; |
| 283 }; | 381 }; |
| 284 | 382 |
| 285 // If true, the next (and immediately following) function literal is | 383 // If true, the next (and immediately following) function literal is |
| 286 // preceded by a parenthesis. | 384 // preceded by a parenthesis. |
| 287 // Heuristically that means that the function will be called immediately, | 385 // Heuristically that means that the function will be called immediately, |
| 288 // so never lazily compile it. | 386 // so never lazily compile it. |
| 289 bool parenthesized_function_; | 387 bool parenthesized_function_; |
| 290 | 388 |
| 389 typename Traits::ScopeClass* scope_; // Scope stack. | |
| 390 FunctionState* function_state_; // Function state stack. | |
| 391 | |
| 291 private: | 392 private: |
| 292 Scanner* scanner_; | 393 Scanner* scanner_; |
| 293 uintptr_t stack_limit_; | 394 uintptr_t stack_limit_; |
| 294 bool stack_overflow_; | 395 bool stack_overflow_; |
| 295 | 396 |
| 296 bool allow_lazy_; | 397 bool allow_lazy_; |
| 297 bool allow_natives_syntax_; | 398 bool allow_natives_syntax_; |
| 298 bool allow_generators_; | 399 bool allow_generators_; |
| 299 bool allow_for_of_; | 400 bool allow_for_of_; |
| 300 }; | 401 }; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 | 528 |
| 428 int code_; | 529 int code_; |
| 429 }; | 530 }; |
| 430 | 531 |
| 431 class PreParser; | 532 class PreParser; |
| 432 | 533 |
| 433 | 534 |
| 434 class PreParserTraits { | 535 class PreParserTraits { |
| 435 public: | 536 public: |
| 436 typedef PreParser* ParserType; | 537 typedef PreParser* ParserType; |
| 538 | |
| 539 // Types used by FunctionState and BlockState. | |
| 540 class Scope; | |
| 541 typedef PreParserTraits::Scope ScopeClass; | |
| 542 class Factory; | |
| 543 typedef PreParserTraits::Factory FactoryType; | |
| 544 // PreParser doesn't need to store generator variables. | |
| 545 typedef void GeneratorVariableType; | |
| 546 typedef void FunctionStateParamType; | |
| 547 | |
| 437 // Return types for traversing functions. | 548 // Return types for traversing functions. |
| 438 typedef PreParserIdentifier IdentifierType; | 549 typedef PreParserIdentifier IdentifierType; |
| 439 typedef PreParserExpression ExpressionType; | 550 typedef PreParserExpression ExpressionType; |
| 440 | 551 |
| 552 class Scope { | |
| 553 public: | |
| 554 explicit Scope(Scope* outer_scope, ScopeType scope_type) | |
| 555 : scope_type_(scope_type) { | |
| 556 if (outer_scope) { | |
| 557 scope_inside_with_ = | |
| 558 outer_scope->scope_inside_with_ || is_with_scope(); | |
| 559 language_mode_ = outer_scope->language_mode(); | |
| 560 } else { | |
| 561 scope_inside_with_ = is_with_scope(); | |
| 562 language_mode_ = CLASSIC_MODE; | |
| 563 } | |
| 564 } | |
| 565 | |
| 566 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; } | |
| 567 bool is_classic_mode() const { | |
| 568 return language_mode() == CLASSIC_MODE; | |
| 569 } | |
| 570 bool is_extended_mode() { | |
| 571 return language_mode() == EXTENDED_MODE; | |
| 572 } | |
| 573 bool inside_with() const { | |
| 574 return scope_inside_with_; | |
| 575 } | |
| 576 | |
| 577 ScopeType type() { return scope_type_; } | |
| 578 LanguageMode language_mode() const { return language_mode_; } | |
| 579 void SetLanguageMode(LanguageMode language_mode) { | |
| 580 language_mode_ = language_mode; | |
| 581 } | |
| 582 | |
| 583 private: | |
| 584 ScopeType scope_type_; | |
| 585 bool scope_inside_with_; | |
| 586 LanguageMode language_mode_; | |
| 587 }; | |
| 588 | |
| 589 class Factory { | |
| 590 public: | |
| 591 explicit Factory(void* extra_param) {} | |
| 592 | |
| 593 ExpressionType NewRegExpLiteral(IdentifierType js_pattern, | |
| 594 IdentifierType js_flags, | |
| 595 int literal_index, | |
| 596 int pos) { | |
| 597 return PreParserExpression::Default(); | |
| 598 } | |
| 599 }; | |
| 600 | |
| 441 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} | 601 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} |
| 442 | 602 |
| 603 // Custom operations executed when FunctionStates are created and | |
| 604 // destructed. (The PreParser doesn't need to do anything.) | |
| 605 template<typename FS> | |
| 606 static void SetUpFunctionState(FS* function_state, void*) {} | |
| 607 template<typename FS> | |
| 608 static void TearDownFunctionState(FS* function_state) {} | |
| 609 | |
| 443 // Helper functions for recursive descent. | 610 // Helper functions for recursive descent. |
| 444 bool is_classic_mode() const; | |
| 445 bool is_generator() const; | |
| 446 static bool IsEvalOrArguments(IdentifierType identifier) { | 611 static bool IsEvalOrArguments(IdentifierType identifier) { |
| 447 return identifier.IsEvalOrArguments(); | 612 return identifier.IsEvalOrArguments(); |
| 448 } | 613 } |
| 449 int NextMaterializedLiteralIndex(); | |
| 450 | 614 |
| 451 // Reporting errors. | 615 // Reporting errors. |
| 452 void ReportMessageAt(Scanner::Location location, | 616 void ReportMessageAt(Scanner::Location location, |
| 453 const char* message, | 617 const char* message, |
| 454 Vector<const char*> args); | 618 Vector<const char*> args); |
| 455 void ReportMessageAt(Scanner::Location location, | 619 void ReportMessageAt(Scanner::Location location, |
| 456 const char* type, | 620 const char* type, |
| 457 const char* name_opt); | 621 const char* name_opt); |
| 458 void ReportMessageAt(int start_pos, | 622 void ReportMessageAt(int start_pos, |
| 459 int end_pos, | 623 int end_pos, |
| 460 const char* type, | 624 const char* type, |
| 461 const char* name_opt); | 625 const char* name_opt); |
| 462 | 626 |
| 463 // "null" return type creators. | 627 // "null" return type creators. |
| 464 static IdentifierType EmptyIdentifier() { | 628 static IdentifierType EmptyIdentifier() { |
| 465 return PreParserIdentifier::Default(); | 629 return PreParserIdentifier::Default(); |
| 466 } | 630 } |
| 467 static ExpressionType EmptyExpression() { | 631 static ExpressionType EmptyExpression() { |
| 468 return PreParserExpression::Default(); | 632 return PreParserExpression::Default(); |
| 469 } | 633 } |
| 470 | 634 |
| 471 // Producing data during the recursive descent. | 635 // Producing data during the recursive descent. |
| 472 IdentifierType GetSymbol(); | 636 IdentifierType GetSymbol(); |
| 473 static IdentifierType NextLiteralString(PretenureFlag tenured) { | 637 static IdentifierType NextLiteralString(PretenureFlag tenured) { |
| 474 return PreParserIdentifier::Default(); | 638 return PreParserIdentifier::Default(); |
| 475 } | 639 } |
| 476 ExpressionType NewRegExpLiteral(IdentifierType js_pattern, | |
| 477 IdentifierType js_flags, | |
| 478 int literal_index, | |
| 479 int pos) { | |
| 480 return PreParserExpression::Default(); | |
| 481 } | |
| 482 | 640 |
| 483 private: | 641 private: |
| 484 PreParser* pre_parser_; | 642 PreParser* pre_parser_; |
| 485 }; | 643 }; |
| 486 | 644 |
| 487 | 645 |
| 488 // Preparsing checks a JavaScript program and emits preparse-data that helps | 646 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 489 // a later parsing to be faster. | 647 // a later parsing to be faster. |
| 490 // See preparse-data-format.h for the data format. | 648 // See preparse-data-format.h for the data format. |
| 491 | 649 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 504 | 662 |
| 505 enum PreParseResult { | 663 enum PreParseResult { |
| 506 kPreParseStackOverflow, | 664 kPreParseStackOverflow, |
| 507 kPreParseSuccess | 665 kPreParseSuccess |
| 508 }; | 666 }; |
| 509 | 667 |
| 510 PreParser(Scanner* scanner, | 668 PreParser(Scanner* scanner, |
| 511 ParserRecorder* log, | 669 ParserRecorder* log, |
| 512 uintptr_t stack_limit) | 670 uintptr_t stack_limit) |
| 513 : ParserBase<PreParserTraits>(scanner, stack_limit, this), | 671 : ParserBase<PreParserTraits>(scanner, stack_limit, this), |
| 514 log_(log), | 672 log_(log) {} |
| 515 function_state_(NULL), | |
| 516 scope_(NULL) { } | |
| 517 | |
| 518 ~PreParser() {} | |
| 519 | 673 |
| 520 // Pre-parse the program from the character stream; returns true on | 674 // Pre-parse the program from the character stream; returns true on |
| 521 // success (even if parsing failed, the pre-parse data successfully | 675 // success (even if parsing failed, the pre-parse data successfully |
| 522 // captured the syntax error), and false if a stack-overflow happened | 676 // captured the syntax error), and false if a stack-overflow happened |
| 523 // during parsing. | 677 // during parsing. |
| 524 PreParseResult PreParseProgram() { | 678 PreParseResult PreParseProgram() { |
| 525 FunctionState top_scope(&function_state_, &scope_, GLOBAL_SCOPE); | 679 PreParserTraits::Scope scope(scope_, GLOBAL_SCOPE); |
| 680 FunctionState top_scope(&function_state_, &scope_, &scope, NULL); | |
| 526 bool ok = true; | 681 bool ok = true; |
| 527 int start_position = scanner()->peek_location().beg_pos; | 682 int start_position = scanner()->peek_location().beg_pos; |
| 528 ParseSourceElements(Token::EOS, &ok); | 683 ParseSourceElements(Token::EOS, &ok); |
| 529 if (stack_overflow()) return kPreParseStackOverflow; | 684 if (stack_overflow()) return kPreParseStackOverflow; |
| 530 if (!ok) { | 685 if (!ok) { |
| 531 ReportUnexpectedToken(scanner()->current_token()); | 686 ReportUnexpectedToken(scanner()->current_token()); |
| 532 } else if (!scope_->is_classic_mode()) { | 687 } else if (!scope_->is_classic_mode()) { |
| 533 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); | 688 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); |
| 534 } | 689 } |
| 535 return kPreParseSuccess; | 690 return kPreParseSuccess; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 613 explicit Statement(Type code) : code_(code) {} | 768 explicit Statement(Type code) : code_(code) {} |
| 614 Type code_; | 769 Type code_; |
| 615 }; | 770 }; |
| 616 | 771 |
| 617 enum SourceElements { | 772 enum SourceElements { |
| 618 kUnknownSourceElements | 773 kUnknownSourceElements |
| 619 }; | 774 }; |
| 620 | 775 |
| 621 typedef int Arguments; | 776 typedef int Arguments; |
| 622 | 777 |
| 623 class Scope { | |
| 624 public: | |
| 625 explicit Scope(Scope* outer_scope, ScopeType scope_type) | |
| 626 : scope_type_(scope_type) { | |
| 627 if (outer_scope) { | |
| 628 scope_inside_with_ = | |
| 629 outer_scope->scope_inside_with_ || is_with_scope(); | |
| 630 language_mode_ = outer_scope->language_mode(); | |
| 631 } else { | |
| 632 scope_inside_with_ = is_with_scope(); | |
| 633 language_mode_ = CLASSIC_MODE; | |
| 634 } | |
| 635 } | |
| 636 | |
| 637 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; } | |
| 638 bool is_classic_mode() const { | |
| 639 return language_mode() == CLASSIC_MODE; | |
| 640 } | |
| 641 bool is_extended_mode() { | |
| 642 return language_mode() == EXTENDED_MODE; | |
| 643 } | |
| 644 bool inside_with() const { | |
| 645 return scope_inside_with_; | |
| 646 } | |
| 647 | |
| 648 ScopeType type() { return scope_type_; } | |
| 649 LanguageMode language_mode() const { return language_mode_; } | |
| 650 void SetLanguageMode(LanguageMode language_mode) { | |
| 651 language_mode_ = language_mode; | |
| 652 } | |
| 653 | |
| 654 private: | |
| 655 ScopeType scope_type_; | |
| 656 bool scope_inside_with_; | |
| 657 LanguageMode language_mode_; | |
| 658 }; | |
| 659 | |
| 660 class FunctionState { | |
| 661 public: | |
| 662 FunctionState(FunctionState** function_state_stack, Scope** scope_stack, | |
| 663 ScopeType scope_type) | |
| 664 : function_state_stack_(function_state_stack), | |
| 665 outer_function_state_(*function_state_stack), | |
| 666 scope_stack_(scope_stack), | |
| 667 outer_scope_(*scope_stack), | |
| 668 scope_(*scope_stack, scope_type), | |
| 669 materialized_literal_count_(0), | |
| 670 expected_properties_(0), | |
| 671 is_generator_(false) { | |
| 672 *scope_stack = &scope_; | |
| 673 *function_state_stack = this; | |
| 674 } | |
| 675 ~FunctionState() { | |
| 676 *scope_stack_ = outer_scope_; | |
| 677 *function_state_stack_ = outer_function_state_; | |
| 678 } | |
| 679 int NextMaterializedLiteralIndex() { return materialized_literal_count_++; } | |
| 680 void AddProperty() { expected_properties_++; } | |
| 681 int expected_properties() { return expected_properties_; } | |
| 682 int materialized_literal_count() { return materialized_literal_count_; } | |
| 683 bool is_generator() { return is_generator_; } | |
| 684 void set_is_generator(bool is_generator) { is_generator_ = is_generator; } | |
| 685 | |
| 686 private: | |
| 687 FunctionState** const function_state_stack_; | |
| 688 FunctionState* const outer_function_state_; | |
| 689 Scope** const scope_stack_; | |
| 690 Scope* const outer_scope_; | |
| 691 Scope scope_; | |
| 692 | |
| 693 int materialized_literal_count_; | |
| 694 int expected_properties_; | |
| 695 LanguageMode language_mode_; | |
| 696 bool is_generator_; | |
| 697 }; | |
| 698 | |
| 699 class BlockState { | |
| 700 public: | |
| 701 BlockState(Scope** scope_stack, ScopeType scope_type) | |
| 702 : scope_stack_(scope_stack), | |
| 703 outer_scope_(*scope_stack), | |
| 704 scope_(*scope_stack, scope_type) { | |
| 705 *scope_stack_ = &scope_; | |
| 706 } | |
| 707 | |
| 708 ~BlockState() { *scope_stack_ = outer_scope_; } | |
| 709 | |
| 710 private: | |
| 711 Scope** scope_stack_; | |
| 712 Scope* outer_scope_; | |
| 713 Scope scope_; | |
| 714 }; | |
| 715 | |
| 716 // All ParseXXX functions take as the last argument an *ok parameter | 778 // All ParseXXX functions take as the last argument an *ok parameter |
| 717 // which is set to false if parsing failed; it is unchanged otherwise. | 779 // which is set to false if parsing failed; it is unchanged otherwise. |
| 718 // By making the 'exception handling' explicit, we are forced to check | 780 // By making the 'exception handling' explicit, we are forced to check |
| 719 // for failure at the call sites. | 781 // for failure at the call sites. |
| 720 Statement ParseSourceElement(bool* ok); | 782 Statement ParseSourceElement(bool* ok); |
| 721 SourceElements ParseSourceElements(int end_token, bool* ok); | 783 SourceElements ParseSourceElements(int end_token, bool* ok); |
| 722 Statement ParseStatement(bool* ok); | 784 Statement ParseStatement(bool* ok); |
| 723 Statement ParseFunctionDeclaration(bool* ok); | 785 Statement ParseFunctionDeclaration(bool* ok); |
| 724 Statement ParseBlock(bool* ok); | 786 Statement ParseBlock(bool* ok); |
| 725 Statement ParseVariableStatement(VariableDeclarationContext var_context, | 787 Statement ParseVariableStatement(VariableDeclarationContext var_context, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 void ParseLazyFunctionLiteralBody(bool* ok); | 830 void ParseLazyFunctionLiteralBody(bool* ok); |
| 769 | 831 |
| 770 // Logs the currently parsed literal as a symbol in the preparser data. | 832 // Logs the currently parsed literal as a symbol in the preparser data. |
| 771 void LogSymbol(); | 833 void LogSymbol(); |
| 772 // Log the currently parsed string literal. | 834 // Log the currently parsed string literal. |
| 773 Expression GetStringSymbol(); | 835 Expression GetStringSymbol(); |
| 774 | 836 |
| 775 bool CheckInOrOf(bool accept_OF); | 837 bool CheckInOrOf(bool accept_OF); |
| 776 | 838 |
| 777 ParserRecorder* log_; | 839 ParserRecorder* log_; |
| 778 FunctionState* function_state_; | |
| 779 Scope* scope_; | |
| 780 }; | 840 }; |
| 781 | 841 |
| 782 | 842 |
| 783 template<class Traits> | 843 template<class Traits> |
| 844 ParserBase<Traits>::FunctionState::FunctionState( | |
| 845 FunctionState** function_state_stack, | |
| 846 typename Traits::ScopeClass** scope_stack, | |
| 847 typename Traits::ScopeClass* scope, | |
| 848 typename Traits::FunctionStateParamType* extra_param) | |
| 849 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize), | |
| 850 next_handler_index_(0), | |
| 851 expected_property_count_(0), | |
| 852 is_generator_(false), | |
| 853 generator_object_variable_(NULL), | |
| 854 function_state_stack_(function_state_stack), | |
| 855 outer_function_state_(*function_state_stack), | |
| 856 scope_stack_(scope_stack), | |
| 857 outer_scope_(*scope_stack), | |
| 858 isolate_(NULL), | |
| 859 saved_ast_node_id_(0), | |
| 860 factory_(extra_param) { | |
| 861 *scope_stack_ = scope; | |
| 862 *function_state_stack = this; | |
| 863 Traits::SetUpFunctionState(this, extra_param); | |
| 864 } | |
| 865 | |
| 866 | |
| 867 template<class Traits> | |
| 868 ParserBase<Traits>::FunctionState::~FunctionState() { | |
| 869 *scope_stack_ = outer_scope_; | |
| 870 *function_state_stack_ = outer_function_state_; | |
| 871 Traits::TearDownFunctionState(this); | |
| 872 } | |
| 873 | |
| 874 | |
| 875 template<class Traits> | |
| 784 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { | 876 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { |
| 785 // We don't report stack overflows here, to avoid increasing the | 877 // We don't report stack overflows here, to avoid increasing the |
| 786 // stack depth even further. Instead we report it after parsing is | 878 // stack depth even further. Instead we report it after parsing is |
| 787 // over, in ParseProgram. | 879 // over, in ParseProgram. |
| 788 if (token == Token::ILLEGAL && stack_overflow()) { | 880 if (token == Token::ILLEGAL && stack_overflow()) { |
| 789 return; | 881 return; |
| 790 } | 882 } |
| 791 Scanner::Location source_location = scanner()->location(); | 883 Scanner::Location source_location = scanner()->location(); |
| 792 | 884 |
| 793 // Four of the tokens are treated specially | 885 // Four of the tokens are treated specially |
| 794 switch (token) { | 886 switch (token) { |
| 795 case Token::EOS: | 887 case Token::EOS: |
| 796 return ReportMessageAt(source_location, "unexpected_eos"); | 888 return ReportMessageAt(source_location, "unexpected_eos"); |
| 797 case Token::NUMBER: | 889 case Token::NUMBER: |
| 798 return ReportMessageAt(source_location, "unexpected_token_number"); | 890 return ReportMessageAt(source_location, "unexpected_token_number"); |
| 799 case Token::STRING: | 891 case Token::STRING: |
| 800 return ReportMessageAt(source_location, "unexpected_token_string"); | 892 return ReportMessageAt(source_location, "unexpected_token_string"); |
| 801 case Token::IDENTIFIER: | 893 case Token::IDENTIFIER: |
| 802 return ReportMessageAt(source_location, "unexpected_token_identifier"); | 894 return ReportMessageAt(source_location, "unexpected_token_identifier"); |
| 803 case Token::FUTURE_RESERVED_WORD: | 895 case Token::FUTURE_RESERVED_WORD: |
| 804 return ReportMessageAt(source_location, "unexpected_reserved"); | 896 return ReportMessageAt(source_location, "unexpected_reserved"); |
| 805 case Token::YIELD: | 897 case Token::YIELD: |
| 806 case Token::FUTURE_STRICT_RESERVED_WORD: | 898 case Token::FUTURE_STRICT_RESERVED_WORD: |
| 807 return ReportMessageAt( | 899 return ReportMessageAt(source_location, |
| 808 source_location, | 900 is_classic_mode() ? "unexpected_token_identifier" |
| 809 this->is_classic_mode() ? "unexpected_token_identifier" | 901 : "unexpected_strict_reserved"); |
| 810 : "unexpected_strict_reserved"); | |
| 811 default: | 902 default: |
| 812 const char* name = Token::String(token); | 903 const char* name = Token::String(token); |
| 813 ASSERT(name != NULL); | 904 ASSERT(name != NULL); |
| 814 Traits::ReportMessageAt( | 905 Traits::ReportMessageAt( |
| 815 source_location, "unexpected_token", Vector<const char*>(&name, 1)); | 906 source_location, "unexpected_token", Vector<const char*>(&name, 1)); |
| 816 } | 907 } |
| 817 } | 908 } |
| 818 | 909 |
| 819 | 910 |
| 820 template<class Traits> | 911 template<class Traits> |
| 821 typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifier( | 912 typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifier( |
| 822 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | 913 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
| 823 bool* ok) { | 914 bool* ok) { |
| 824 Token::Value next = Next(); | 915 Token::Value next = Next(); |
| 825 if (next == Token::IDENTIFIER) { | 916 if (next == Token::IDENTIFIER) { |
| 826 typename Traits::IdentifierType name = this->GetSymbol(); | 917 typename Traits::IdentifierType name = this->GetSymbol(); |
| 827 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | 918 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
| 828 !this->is_classic_mode() && this->IsEvalOrArguments(name)) { | 919 !is_classic_mode() && this->IsEvalOrArguments(name)) { |
| 829 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); | 920 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); |
| 830 *ok = false; | 921 *ok = false; |
| 831 } | 922 } |
| 832 return name; | 923 return name; |
| 833 } else if (this->is_classic_mode() && | 924 } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 834 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 925 (next == Token::YIELD && !is_generator()))) { |
| 835 (next == Token::YIELD && !this->is_generator()))) { | |
| 836 return this->GetSymbol(); | 926 return this->GetSymbol(); |
| 837 } else { | 927 } else { |
| 838 this->ReportUnexpectedToken(next); | 928 this->ReportUnexpectedToken(next); |
| 839 *ok = false; | 929 *ok = false; |
| 840 return Traits::EmptyIdentifier(); | 930 return Traits::EmptyIdentifier(); |
| 841 } | 931 } |
| 842 } | 932 } |
| 843 | 933 |
| 844 | 934 |
| 845 template <class Traits> | 935 template <class Traits> |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 896 typename Traits::ExpressionType | 986 typename Traits::ExpressionType |
| 897 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { | 987 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { |
| 898 int pos = peek_position(); | 988 int pos = peek_position(); |
| 899 if (!scanner()->ScanRegExpPattern(seen_equal)) { | 989 if (!scanner()->ScanRegExpPattern(seen_equal)) { |
| 900 Next(); | 990 Next(); |
| 901 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); | 991 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); |
| 902 *ok = false; | 992 *ok = false; |
| 903 return Traits::EmptyExpression(); | 993 return Traits::EmptyExpression(); |
| 904 } | 994 } |
| 905 | 995 |
| 906 int literal_index = this->NextMaterializedLiteralIndex(); | 996 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
| 907 | 997 |
| 908 typename Traits::IdentifierType js_pattern = this->NextLiteralString(TENURED); | 998 typename Traits::IdentifierType js_pattern = this->NextLiteralString(TENURED); |
| 909 if (!scanner()->ScanRegExpFlags()) { | 999 if (!scanner()->ScanRegExpFlags()) { |
| 910 Next(); | 1000 Next(); |
| 911 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); | 1001 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); |
| 912 *ok = false; | 1002 *ok = false; |
| 913 return Traits::EmptyExpression(); | 1003 return Traits::EmptyExpression(); |
| 914 } | 1004 } |
| 915 typename Traits::IdentifierType js_flags = this->NextLiteralString(TENURED); | 1005 typename Traits::IdentifierType js_flags = this->NextLiteralString(TENURED); |
| 916 Next(); | 1006 Next(); |
| 917 return this->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); | 1007 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); |
| 918 } | 1008 } |
| 919 | 1009 |
| 920 | 1010 |
| 921 template <typename Traits> | 1011 template <typename Traits> |
| 922 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | 1012 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( |
| 923 Token::Value property, | 1013 Token::Value property, |
| 924 PropertyKind type, | 1014 PropertyKind type, |
| 925 bool* ok) { | 1015 bool* ok) { |
| 926 int old; | 1016 int old; |
| 927 if (property == Token::NUMBER) { | 1017 if (property == Token::NUMBER) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 949 "accessor_get_set"); | 1039 "accessor_get_set"); |
| 950 } | 1040 } |
| 951 *ok = false; | 1041 *ok = false; |
| 952 } | 1042 } |
| 953 } | 1043 } |
| 954 | 1044 |
| 955 | 1045 |
| 956 } } // v8::internal | 1046 } } // v8::internal |
| 957 | 1047 |
| 958 #endif // V8_PREPARSER_H | 1048 #endif // V8_PREPARSER_H |
| OLD | NEW |