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 |