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::Type::Parser 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::Type::Scope** scope_stack, |
| 97 typename Traits::Type::Scope* 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::Type::Scope** scope_stack_; |
| 107 typename Traits::Type::Scope* outer_scope_; |
| 108 typename Traits::Type::Scope* scope_; |
| 109 }; |
| 110 |
| 111 class FunctionState BASE_EMBEDDED { |
| 112 public: |
| 113 FunctionState( |
| 114 FunctionState** function_state_stack, |
| 115 typename Traits::Type::Scope** scope_stack, |
| 116 typename Traits::Type::Scope* scope, |
| 117 typename Traits::Type::Zone* zone = NULL); |
| 118 ~FunctionState(); |
| 119 |
| 120 int NextMaterializedLiteralIndex() { |
| 121 return next_materialized_literal_index_++; |
| 122 } |
| 123 int materialized_literal_count() { |
| 124 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize; |
| 125 } |
| 126 |
| 127 int NextHandlerIndex() { return next_handler_index_++; } |
| 128 int handler_count() { return next_handler_index_; } |
| 129 |
| 130 void AddProperty() { expected_property_count_++; } |
| 131 int expected_property_count() { return expected_property_count_; } |
| 132 |
| 133 void set_is_generator(bool is_generator) { is_generator_ = is_generator; } |
| 134 bool is_generator() const { return is_generator_; } |
| 135 |
| 136 void set_generator_object_variable( |
| 137 typename Traits::Type::GeneratorVariable* variable) { |
| 138 ASSERT(variable != NULL); |
| 139 ASSERT(!is_generator()); |
| 140 generator_object_variable_ = variable; |
| 141 is_generator_ = true; |
| 142 } |
| 143 typename Traits::Type::GeneratorVariable* generator_object_variable() |
| 144 const { |
| 145 return generator_object_variable_; |
| 146 } |
| 147 |
| 148 typename Traits::Type::Factory* factory() { return &factory_; } |
| 149 |
| 150 private: |
| 151 // Used to assign an index to each literal that needs materialization in |
| 152 // the function. Includes regexp literals, and boilerplate for object and |
| 153 // array literals. |
| 154 int next_materialized_literal_index_; |
| 155 |
| 156 // Used to assign a per-function index to try and catch handlers. |
| 157 int next_handler_index_; |
| 158 |
| 159 // Properties count estimation. |
| 160 int expected_property_count_; |
| 161 |
| 162 // Whether the function is a generator. |
| 163 bool is_generator_; |
| 164 // For generators, this variable may hold the generator object. It variable |
| 165 // is used by yield expressions and return statements. It is not necessary |
| 166 // for generator functions to have this variable set. |
| 167 Variable* generator_object_variable_; |
| 168 |
| 169 FunctionState** function_state_stack_; |
| 170 FunctionState* outer_function_state_; |
| 171 typename Traits::Type::Scope** scope_stack_; |
| 172 typename Traits::Type::Scope* outer_scope_; |
| 173 Isolate* isolate_; // Only used by ParserTraits. |
| 174 int saved_ast_node_id_; // Only used by ParserTraits. |
| 175 typename Traits::Type::Factory factory_; |
| 176 |
| 177 friend class ParserTraits; |
| 178 }; |
| 179 |
86 Scanner* scanner() const { return scanner_; } | 180 Scanner* scanner() const { return scanner_; } |
87 int position() { return scanner_->location().beg_pos; } | 181 int position() { return scanner_->location().beg_pos; } |
88 int peek_position() { return scanner_->peek_location().beg_pos; } | 182 int peek_position() { return scanner_->peek_location().beg_pos; } |
89 bool stack_overflow() const { return stack_overflow_; } | 183 bool stack_overflow() const { return stack_overflow_; } |
90 void set_stack_overflow() { stack_overflow_ = true; } | 184 void set_stack_overflow() { stack_overflow_ = true; } |
91 | 185 |
92 INLINE(Token::Value peek()) { | 186 INLINE(Token::Value peek()) { |
93 if (stack_overflow_) return Token::ILLEGAL; | 187 if (stack_overflow_) return Token::ILLEGAL; |
94 return scanner()->peek(); | 188 return scanner()->peek(); |
95 } | 189 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 } | 280 } |
187 } | 281 } |
188 | 282 |
189 // Determine precedence of given token. | 283 // Determine precedence of given token. |
190 static int Precedence(Token::Value token, bool accept_IN) { | 284 static int Precedence(Token::Value token, bool accept_IN) { |
191 if (token == Token::IN && !accept_IN) | 285 if (token == Token::IN && !accept_IN) |
192 return 0; // 0 precedence will terminate binary expression parsing | 286 return 0; // 0 precedence will terminate binary expression parsing |
193 return Token::Precedence(token); | 287 return Token::Precedence(token); |
194 } | 288 } |
195 | 289 |
| 290 typename Traits::Type::Factory* factory() { |
| 291 return function_state_->factory(); |
| 292 } |
| 293 |
| 294 bool is_classic_mode() const { return scope_->is_classic_mode(); } |
| 295 |
| 296 bool is_generator() const { return function_state_->is_generator(); } |
| 297 |
196 // Report syntax errors. | 298 // Report syntax errors. |
197 void ReportMessage(const char* message, Vector<const char*> args) { | 299 void ReportMessage(const char* message, Vector<const char*> args) { |
198 Scanner::Location source_location = scanner()->location(); | 300 Scanner::Location source_location = scanner()->location(); |
199 Traits::ReportMessageAt(source_location, message, args); | 301 Traits::ReportMessageAt(source_location, message, args); |
200 } | 302 } |
201 | 303 |
202 void ReportMessageAt(Scanner::Location location, const char* message) { | 304 void ReportMessageAt(Scanner::Location location, const char* message) { |
203 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); | 305 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); |
204 } | 306 } |
205 | 307 |
206 void ReportUnexpectedToken(Token::Value token); | 308 void ReportUnexpectedToken(Token::Value token); |
207 | 309 |
208 // Recursive descent functions: | 310 // Recursive descent functions: |
209 | 311 |
210 // Parses an identifier that is valid for the current scope, in particular it | 312 // Parses an identifier that is valid for the current scope, in particular it |
211 // fails on strict mode future reserved keywords in a strict scope. If | 313 // fails on strict mode future reserved keywords in a strict scope. If |
212 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | 314 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
213 // "arguments" as identifier even in strict mode (this is needed in cases like | 315 // "arguments" as identifier even in strict mode (this is needed in cases like |
214 // "var foo = eval;"). | 316 // "var foo = eval;"). |
215 typename Traits::IdentifierType ParseIdentifier( | 317 typename Traits::Type::Identifier ParseIdentifier( |
216 AllowEvalOrArgumentsAsIdentifier, | 318 AllowEvalOrArgumentsAsIdentifier, |
217 bool* ok); | 319 bool* ok); |
218 // Parses an identifier or a strict mode future reserved word, and indicate | 320 // Parses an identifier or a strict mode future reserved word, and indicate |
219 // whether it is strict mode future reserved. | 321 // whether it is strict mode future reserved. |
220 typename Traits::IdentifierType ParseIdentifierOrStrictReservedWord( | 322 typename Traits::Type::Identifier ParseIdentifierOrStrictReservedWord( |
221 bool* is_strict_reserved, | 323 bool* is_strict_reserved, |
222 bool* ok); | 324 bool* ok); |
223 typename Traits::IdentifierType ParseIdentifierName(bool* ok); | 325 typename Traits::Type::Identifier ParseIdentifierName(bool* ok); |
224 // Parses an identifier and determines whether or not it is 'get' or 'set'. | 326 // Parses an identifier and determines whether or not it is 'get' or 'set'. |
225 typename Traits::IdentifierType ParseIdentifierNameOrGetOrSet(bool* is_get, | 327 typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, |
226 bool* is_set, | 328 bool* is_set, |
227 bool* ok); | 329 bool* ok); |
228 | 330 |
229 typename Traits::ExpressionType ParseRegExpLiteral(bool seen_equal, bool* ok); | 331 typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal, |
| 332 bool* ok); |
230 | 333 |
231 // Used to detect duplicates in object literals. Each of the values | 334 // Used to detect duplicates in object literals. Each of the values |
232 // kGetterProperty, kSetterProperty and kValueProperty represents | 335 // kGetterProperty, kSetterProperty and kValueProperty represents |
233 // a type of object literal property. When parsing a property, its | 336 // a type of object literal property. When parsing a property, its |
234 // type value is stored in the DuplicateFinder for the property name. | 337 // type value is stored in the DuplicateFinder for the property name. |
235 // Values are chosen so that having intersection bits means the there is | 338 // Values are chosen so that having intersection bits means the there is |
236 // an incompatibility. | 339 // an incompatibility. |
237 // I.e., you can add a getter to a property that already has a setter, since | 340 // I.e., you can add a getter to a property that already has a setter, since |
238 // kGetterProperty and kSetterProperty doesn't intersect, but not if it | 341 // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
239 // already has a getter or a value. Adding the getter to an existing | 342 // already has a getter or a value. Adding the getter to an existing |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 DuplicateFinder finder_; | 384 DuplicateFinder finder_; |
282 LanguageMode language_mode_; | 385 LanguageMode language_mode_; |
283 }; | 386 }; |
284 | 387 |
285 // If true, the next (and immediately following) function literal is | 388 // If true, the next (and immediately following) function literal is |
286 // preceded by a parenthesis. | 389 // preceded by a parenthesis. |
287 // Heuristically that means that the function will be called immediately, | 390 // Heuristically that means that the function will be called immediately, |
288 // so never lazily compile it. | 391 // so never lazily compile it. |
289 bool parenthesized_function_; | 392 bool parenthesized_function_; |
290 | 393 |
| 394 typename Traits::Type::Scope* scope_; // Scope stack. |
| 395 FunctionState* function_state_; // Function state stack. |
| 396 |
291 private: | 397 private: |
292 Scanner* scanner_; | 398 Scanner* scanner_; |
293 uintptr_t stack_limit_; | 399 uintptr_t stack_limit_; |
294 bool stack_overflow_; | 400 bool stack_overflow_; |
295 | 401 |
296 bool allow_lazy_; | 402 bool allow_lazy_; |
297 bool allow_natives_syntax_; | 403 bool allow_natives_syntax_; |
298 bool allow_generators_; | 404 bool allow_generators_; |
299 bool allow_for_of_; | 405 bool allow_for_of_; |
300 }; | 406 }; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 kThisExpression = 4, | 527 kThisExpression = 4, |
422 kThisPropertyExpression = 8, | 528 kThisPropertyExpression = 8, |
423 kStrictFunctionExpression = 12 | 529 kStrictFunctionExpression = 12 |
424 }; | 530 }; |
425 | 531 |
426 explicit PreParserExpression(int expression_code) : code_(expression_code) {} | 532 explicit PreParserExpression(int expression_code) : code_(expression_code) {} |
427 | 533 |
428 int code_; | 534 int code_; |
429 }; | 535 }; |
430 | 536 |
| 537 |
| 538 class PreParserScope { |
| 539 public: |
| 540 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type) |
| 541 : scope_type_(scope_type) { |
| 542 if (outer_scope) { |
| 543 scope_inside_with_ = |
| 544 outer_scope->scope_inside_with_ || is_with_scope(); |
| 545 language_mode_ = outer_scope->language_mode(); |
| 546 } else { |
| 547 scope_inside_with_ = is_with_scope(); |
| 548 language_mode_ = CLASSIC_MODE; |
| 549 } |
| 550 } |
| 551 |
| 552 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; } |
| 553 bool is_classic_mode() const { |
| 554 return language_mode() == CLASSIC_MODE; |
| 555 } |
| 556 bool is_extended_mode() { |
| 557 return language_mode() == EXTENDED_MODE; |
| 558 } |
| 559 bool inside_with() const { |
| 560 return scope_inside_with_; |
| 561 } |
| 562 |
| 563 ScopeType type() { return scope_type_; } |
| 564 LanguageMode language_mode() const { return language_mode_; } |
| 565 void SetLanguageMode(LanguageMode language_mode) { |
| 566 language_mode_ = language_mode; |
| 567 } |
| 568 |
| 569 private: |
| 570 ScopeType scope_type_; |
| 571 bool scope_inside_with_; |
| 572 LanguageMode language_mode_; |
| 573 }; |
| 574 |
| 575 |
| 576 class PreParserFactory { |
| 577 public: |
| 578 explicit PreParserFactory(void* extra_param) {} |
| 579 |
| 580 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, |
| 581 PreParserIdentifier js_flags, |
| 582 int literal_index, |
| 583 int pos) { |
| 584 return PreParserExpression::Default(); |
| 585 } |
| 586 }; |
| 587 |
| 588 |
431 class PreParser; | 589 class PreParser; |
432 | 590 |
433 | |
434 class PreParserTraits { | 591 class PreParserTraits { |
435 public: | 592 public: |
436 typedef PreParser* ParserType; | 593 struct Type { |
437 // Return types for traversing functions. | 594 typedef PreParser* Parser; |
438 typedef PreParserIdentifier IdentifierType; | 595 |
439 typedef PreParserExpression ExpressionType; | 596 // Types used by FunctionState and BlockState. |
| 597 typedef PreParserScope Scope; |
| 598 typedef PreParserFactory Factory; |
| 599 // PreParser doesn't need to store generator variables. |
| 600 typedef void GeneratorVariable; |
| 601 // No interaction with Zones. |
| 602 typedef void Zone; |
| 603 |
| 604 // Return types for traversing functions. |
| 605 typedef PreParserIdentifier Identifier; |
| 606 typedef PreParserExpression Expression; |
| 607 }; |
440 | 608 |
441 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} | 609 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} |
442 | 610 |
| 611 // Custom operations executed when FunctionStates are created and |
| 612 // destructed. (The PreParser doesn't need to do anything.) |
| 613 template<typename FS> |
| 614 static void SetUpFunctionState(FS* function_state, void*) {} |
| 615 template<typename FS> |
| 616 static void TearDownFunctionState(FS* function_state) {} |
| 617 |
443 // Helper functions for recursive descent. | 618 // Helper functions for recursive descent. |
444 bool is_classic_mode() const; | 619 static bool IsEvalOrArguments(PreParserIdentifier identifier) { |
445 bool is_generator() const; | |
446 static bool IsEvalOrArguments(IdentifierType identifier) { | |
447 return identifier.IsEvalOrArguments(); | 620 return identifier.IsEvalOrArguments(); |
448 } | 621 } |
449 int NextMaterializedLiteralIndex(); | |
450 | 622 |
451 // Reporting errors. | 623 // Reporting errors. |
452 void ReportMessageAt(Scanner::Location location, | 624 void ReportMessageAt(Scanner::Location location, |
453 const char* message, | 625 const char* message, |
454 Vector<const char*> args); | 626 Vector<const char*> args); |
455 void ReportMessageAt(Scanner::Location location, | 627 void ReportMessageAt(Scanner::Location location, |
456 const char* type, | 628 const char* type, |
457 const char* name_opt); | 629 const char* name_opt); |
458 void ReportMessageAt(int start_pos, | 630 void ReportMessageAt(int start_pos, |
459 int end_pos, | 631 int end_pos, |
460 const char* type, | 632 const char* type, |
461 const char* name_opt); | 633 const char* name_opt); |
462 | 634 |
463 // "null" return type creators. | 635 // "null" return type creators. |
464 static IdentifierType EmptyIdentifier() { | 636 static PreParserIdentifier EmptyIdentifier() { |
465 return PreParserIdentifier::Default(); | 637 return PreParserIdentifier::Default(); |
466 } | 638 } |
467 static ExpressionType EmptyExpression() { | 639 static PreParserExpression EmptyExpression() { |
468 return PreParserExpression::Default(); | 640 return PreParserExpression::Default(); |
469 } | 641 } |
470 | 642 |
471 // Producing data during the recursive descent. | 643 // Producing data during the recursive descent. |
472 IdentifierType GetSymbol(); | 644 PreParserIdentifier GetSymbol(); |
473 static IdentifierType NextLiteralString(PretenureFlag tenured) { | 645 static PreParserIdentifier NextLiteralString(PretenureFlag tenured) { |
474 return PreParserIdentifier::Default(); | 646 return PreParserIdentifier::Default(); |
475 } | 647 } |
476 ExpressionType NewRegExpLiteral(IdentifierType js_pattern, | |
477 IdentifierType js_flags, | |
478 int literal_index, | |
479 int pos) { | |
480 return PreParserExpression::Default(); | |
481 } | |
482 | 648 |
483 private: | 649 private: |
484 PreParser* pre_parser_; | 650 PreParser* pre_parser_; |
485 }; | 651 }; |
486 | 652 |
487 | 653 |
488 // Preparsing checks a JavaScript program and emits preparse-data that helps | 654 // Preparsing checks a JavaScript program and emits preparse-data that helps |
489 // a later parsing to be faster. | 655 // a later parsing to be faster. |
490 // See preparse-data-format.h for the data format. | 656 // See preparse-data-format.h for the data format. |
491 | 657 |
(...skipping 12 matching lines...) Expand all Loading... |
504 | 670 |
505 enum PreParseResult { | 671 enum PreParseResult { |
506 kPreParseStackOverflow, | 672 kPreParseStackOverflow, |
507 kPreParseSuccess | 673 kPreParseSuccess |
508 }; | 674 }; |
509 | 675 |
510 PreParser(Scanner* scanner, | 676 PreParser(Scanner* scanner, |
511 ParserRecorder* log, | 677 ParserRecorder* log, |
512 uintptr_t stack_limit) | 678 uintptr_t stack_limit) |
513 : ParserBase<PreParserTraits>(scanner, stack_limit, this), | 679 : ParserBase<PreParserTraits>(scanner, stack_limit, this), |
514 log_(log), | 680 log_(log) {} |
515 function_state_(NULL), | |
516 scope_(NULL) { } | |
517 | |
518 ~PreParser() {} | |
519 | 681 |
520 // Pre-parse the program from the character stream; returns true on | 682 // Pre-parse the program from the character stream; returns true on |
521 // success (even if parsing failed, the pre-parse data successfully | 683 // success (even if parsing failed, the pre-parse data successfully |
522 // captured the syntax error), and false if a stack-overflow happened | 684 // captured the syntax error), and false if a stack-overflow happened |
523 // during parsing. | 685 // during parsing. |
524 PreParseResult PreParseProgram() { | 686 PreParseResult PreParseProgram() { |
525 FunctionState top_scope(&function_state_, &scope_, GLOBAL_SCOPE); | 687 PreParserScope scope(scope_, GLOBAL_SCOPE); |
| 688 FunctionState top_scope(&function_state_, &scope_, &scope, NULL); |
526 bool ok = true; | 689 bool ok = true; |
527 int start_position = scanner()->peek_location().beg_pos; | 690 int start_position = scanner()->peek_location().beg_pos; |
528 ParseSourceElements(Token::EOS, &ok); | 691 ParseSourceElements(Token::EOS, &ok); |
529 if (stack_overflow()) return kPreParseStackOverflow; | 692 if (stack_overflow()) return kPreParseStackOverflow; |
530 if (!ok) { | 693 if (!ok) { |
531 ReportUnexpectedToken(scanner()->current_token()); | 694 ReportUnexpectedToken(scanner()->current_token()); |
532 } else if (!scope_->is_classic_mode()) { | 695 } else if (!scope_->is_classic_mode()) { |
533 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); | 696 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); |
534 } | 697 } |
535 return kPreParseSuccess; | 698 return kPreParseSuccess; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 explicit Statement(Type code) : code_(code) {} | 776 explicit Statement(Type code) : code_(code) {} |
614 Type code_; | 777 Type code_; |
615 }; | 778 }; |
616 | 779 |
617 enum SourceElements { | 780 enum SourceElements { |
618 kUnknownSourceElements | 781 kUnknownSourceElements |
619 }; | 782 }; |
620 | 783 |
621 typedef int Arguments; | 784 typedef int Arguments; |
622 | 785 |
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 bool is_generator_; | |
696 }; | |
697 | |
698 class BlockState { | |
699 public: | |
700 BlockState(Scope** scope_stack, ScopeType scope_type) | |
701 : scope_stack_(scope_stack), | |
702 outer_scope_(*scope_stack), | |
703 scope_(*scope_stack, scope_type) { | |
704 *scope_stack_ = &scope_; | |
705 } | |
706 | |
707 ~BlockState() { *scope_stack_ = outer_scope_; } | |
708 | |
709 private: | |
710 Scope** scope_stack_; | |
711 Scope* outer_scope_; | |
712 Scope scope_; | |
713 }; | |
714 | |
715 // All ParseXXX functions take as the last argument an *ok parameter | 786 // All ParseXXX functions take as the last argument an *ok parameter |
716 // which is set to false if parsing failed; it is unchanged otherwise. | 787 // which is set to false if parsing failed; it is unchanged otherwise. |
717 // By making the 'exception handling' explicit, we are forced to check | 788 // By making the 'exception handling' explicit, we are forced to check |
718 // for failure at the call sites. | 789 // for failure at the call sites. |
719 Statement ParseSourceElement(bool* ok); | 790 Statement ParseSourceElement(bool* ok); |
720 SourceElements ParseSourceElements(int end_token, bool* ok); | 791 SourceElements ParseSourceElements(int end_token, bool* ok); |
721 Statement ParseStatement(bool* ok); | 792 Statement ParseStatement(bool* ok); |
722 Statement ParseFunctionDeclaration(bool* ok); | 793 Statement ParseFunctionDeclaration(bool* ok); |
723 Statement ParseBlock(bool* ok); | 794 Statement ParseBlock(bool* ok); |
724 Statement ParseVariableStatement(VariableDeclarationContext var_context, | 795 Statement ParseVariableStatement(VariableDeclarationContext var_context, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 void ParseLazyFunctionLiteralBody(bool* ok); | 838 void ParseLazyFunctionLiteralBody(bool* ok); |
768 | 839 |
769 // Logs the currently parsed literal as a symbol in the preparser data. | 840 // Logs the currently parsed literal as a symbol in the preparser data. |
770 void LogSymbol(); | 841 void LogSymbol(); |
771 // Log the currently parsed string literal. | 842 // Log the currently parsed string literal. |
772 Expression GetStringSymbol(); | 843 Expression GetStringSymbol(); |
773 | 844 |
774 bool CheckInOrOf(bool accept_OF); | 845 bool CheckInOrOf(bool accept_OF); |
775 | 846 |
776 ParserRecorder* log_; | 847 ParserRecorder* log_; |
777 FunctionState* function_state_; | |
778 Scope* scope_; | |
779 }; | 848 }; |
780 | 849 |
781 | 850 |
782 template<class Traits> | 851 template<class Traits> |
| 852 ParserBase<Traits>::FunctionState::FunctionState( |
| 853 FunctionState** function_state_stack, |
| 854 typename Traits::Type::Scope** scope_stack, |
| 855 typename Traits::Type::Scope* scope, |
| 856 typename Traits::Type::Zone* extra_param) |
| 857 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize), |
| 858 next_handler_index_(0), |
| 859 expected_property_count_(0), |
| 860 is_generator_(false), |
| 861 generator_object_variable_(NULL), |
| 862 function_state_stack_(function_state_stack), |
| 863 outer_function_state_(*function_state_stack), |
| 864 scope_stack_(scope_stack), |
| 865 outer_scope_(*scope_stack), |
| 866 isolate_(NULL), |
| 867 saved_ast_node_id_(0), |
| 868 factory_(extra_param) { |
| 869 *scope_stack_ = scope; |
| 870 *function_state_stack = this; |
| 871 Traits::SetUpFunctionState(this, extra_param); |
| 872 } |
| 873 |
| 874 |
| 875 template<class Traits> |
| 876 ParserBase<Traits>::FunctionState::~FunctionState() { |
| 877 *scope_stack_ = outer_scope_; |
| 878 *function_state_stack_ = outer_function_state_; |
| 879 Traits::TearDownFunctionState(this); |
| 880 } |
| 881 |
| 882 |
| 883 template<class Traits> |
783 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { | 884 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { |
784 // We don't report stack overflows here, to avoid increasing the | 885 // We don't report stack overflows here, to avoid increasing the |
785 // stack depth even further. Instead we report it after parsing is | 886 // stack depth even further. Instead we report it after parsing is |
786 // over, in ParseProgram. | 887 // over, in ParseProgram. |
787 if (token == Token::ILLEGAL && stack_overflow()) { | 888 if (token == Token::ILLEGAL && stack_overflow()) { |
788 return; | 889 return; |
789 } | 890 } |
790 Scanner::Location source_location = scanner()->location(); | 891 Scanner::Location source_location = scanner()->location(); |
791 | 892 |
792 // Four of the tokens are treated specially | 893 // Four of the tokens are treated specially |
793 switch (token) { | 894 switch (token) { |
794 case Token::EOS: | 895 case Token::EOS: |
795 return ReportMessageAt(source_location, "unexpected_eos"); | 896 return ReportMessageAt(source_location, "unexpected_eos"); |
796 case Token::NUMBER: | 897 case Token::NUMBER: |
797 return ReportMessageAt(source_location, "unexpected_token_number"); | 898 return ReportMessageAt(source_location, "unexpected_token_number"); |
798 case Token::STRING: | 899 case Token::STRING: |
799 return ReportMessageAt(source_location, "unexpected_token_string"); | 900 return ReportMessageAt(source_location, "unexpected_token_string"); |
800 case Token::IDENTIFIER: | 901 case Token::IDENTIFIER: |
801 return ReportMessageAt(source_location, "unexpected_token_identifier"); | 902 return ReportMessageAt(source_location, "unexpected_token_identifier"); |
802 case Token::FUTURE_RESERVED_WORD: | 903 case Token::FUTURE_RESERVED_WORD: |
803 return ReportMessageAt(source_location, "unexpected_reserved"); | 904 return ReportMessageAt(source_location, "unexpected_reserved"); |
804 case Token::YIELD: | 905 case Token::YIELD: |
805 case Token::FUTURE_STRICT_RESERVED_WORD: | 906 case Token::FUTURE_STRICT_RESERVED_WORD: |
806 return ReportMessageAt( | 907 return ReportMessageAt(source_location, |
807 source_location, | 908 is_classic_mode() ? "unexpected_token_identifier" |
808 this->is_classic_mode() ? "unexpected_token_identifier" | 909 : "unexpected_strict_reserved"); |
809 : "unexpected_strict_reserved"); | |
810 default: | 910 default: |
811 const char* name = Token::String(token); | 911 const char* name = Token::String(token); |
812 ASSERT(name != NULL); | 912 ASSERT(name != NULL); |
813 Traits::ReportMessageAt( | 913 Traits::ReportMessageAt( |
814 source_location, "unexpected_token", Vector<const char*>(&name, 1)); | 914 source_location, "unexpected_token", Vector<const char*>(&name, 1)); |
815 } | 915 } |
816 } | 916 } |
817 | 917 |
818 | 918 |
819 template<class Traits> | 919 template<class Traits> |
820 typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifier( | 920 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier( |
821 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | 921 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
822 bool* ok) { | 922 bool* ok) { |
823 Token::Value next = Next(); | 923 Token::Value next = Next(); |
824 if (next == Token::IDENTIFIER) { | 924 if (next == Token::IDENTIFIER) { |
825 typename Traits::IdentifierType name = this->GetSymbol(); | 925 typename Traits::Type::Identifier name = this->GetSymbol(); |
826 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | 926 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
827 !this->is_classic_mode() && this->IsEvalOrArguments(name)) { | 927 !is_classic_mode() && this->IsEvalOrArguments(name)) { |
828 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); | 928 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); |
829 *ok = false; | 929 *ok = false; |
830 } | 930 } |
831 return name; | 931 return name; |
832 } else if (this->is_classic_mode() && | 932 } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD || |
833 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 933 (next == Token::YIELD && !is_generator()))) { |
834 (next == Token::YIELD && !this->is_generator()))) { | |
835 return this->GetSymbol(); | 934 return this->GetSymbol(); |
836 } else { | 935 } else { |
837 this->ReportUnexpectedToken(next); | 936 this->ReportUnexpectedToken(next); |
838 *ok = false; | 937 *ok = false; |
839 return Traits::EmptyIdentifier(); | 938 return Traits::EmptyIdentifier(); |
840 } | 939 } |
841 } | 940 } |
842 | 941 |
843 | 942 |
844 template <class Traits> | 943 template <class Traits> |
845 typename Traits::IdentifierType ParserBase< | 944 typename Traits::Type::Identifier ParserBase< |
846 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | 945 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
847 bool* ok) { | 946 bool* ok) { |
848 Token::Value next = Next(); | 947 Token::Value next = Next(); |
849 if (next == Token::IDENTIFIER) { | 948 if (next == Token::IDENTIFIER) { |
850 *is_strict_reserved = false; | 949 *is_strict_reserved = false; |
851 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || | 950 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || |
852 (next == Token::YIELD && !this->is_generator())) { | 951 (next == Token::YIELD && !this->is_generator())) { |
853 *is_strict_reserved = true; | 952 *is_strict_reserved = true; |
854 } else { | 953 } else { |
855 ReportUnexpectedToken(next); | 954 ReportUnexpectedToken(next); |
856 *ok = false; | 955 *ok = false; |
857 return Traits::EmptyIdentifier(); | 956 return Traits::EmptyIdentifier(); |
858 } | 957 } |
859 return this->GetSymbol(); | 958 return this->GetSymbol(); |
860 } | 959 } |
861 | 960 |
862 | 961 |
863 template <class Traits> | 962 template <class Traits> |
864 typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifierName( | 963 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName( |
865 bool* ok) { | 964 bool* ok) { |
866 Token::Value next = Next(); | 965 Token::Value next = Next(); |
867 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && | 966 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && |
868 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { | 967 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { |
869 this->ReportUnexpectedToken(next); | 968 this->ReportUnexpectedToken(next); |
870 *ok = false; | 969 *ok = false; |
871 return Traits::EmptyIdentifier(); | 970 return Traits::EmptyIdentifier(); |
872 } | 971 } |
873 return this->GetSymbol(); | 972 return this->GetSymbol(); |
874 } | 973 } |
875 | 974 |
876 | 975 |
877 template <class Traits> | 976 template <class Traits> |
878 typename Traits::IdentifierType | 977 typename Traits::Type::Identifier |
879 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, | 978 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, |
880 bool* is_set, | 979 bool* is_set, |
881 bool* ok) { | 980 bool* ok) { |
882 typename Traits::IdentifierType result = ParseIdentifierName(ok); | 981 typename Traits::Type::Identifier result = ParseIdentifierName(ok); |
883 if (!*ok) return Traits::EmptyIdentifier(); | 982 if (!*ok) return Traits::EmptyIdentifier(); |
884 if (scanner()->is_literal_ascii() && | 983 if (scanner()->is_literal_ascii() && |
885 scanner()->literal_length() == 3) { | 984 scanner()->literal_length() == 3) { |
886 const char* token = scanner()->literal_ascii_string().start(); | 985 const char* token = scanner()->literal_ascii_string().start(); |
887 *is_get = strncmp(token, "get", 3) == 0; | 986 *is_get = strncmp(token, "get", 3) == 0; |
888 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | 987 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
889 } | 988 } |
890 return result; | 989 return result; |
891 } | 990 } |
892 | 991 |
893 | 992 |
894 template <class Traits> | 993 template <class Traits> |
895 typename Traits::ExpressionType | 994 typename Traits::Type::Expression |
896 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { | 995 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { |
897 int pos = peek_position(); | 996 int pos = peek_position(); |
898 if (!scanner()->ScanRegExpPattern(seen_equal)) { | 997 if (!scanner()->ScanRegExpPattern(seen_equal)) { |
899 Next(); | 998 Next(); |
900 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); | 999 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); |
901 *ok = false; | 1000 *ok = false; |
902 return Traits::EmptyExpression(); | 1001 return Traits::EmptyExpression(); |
903 } | 1002 } |
904 | 1003 |
905 int literal_index = this->NextMaterializedLiteralIndex(); | 1004 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
906 | 1005 |
907 typename Traits::IdentifierType js_pattern = this->NextLiteralString(TENURED); | 1006 typename Traits::Type::Identifier js_pattern = |
| 1007 this->NextLiteralString(TENURED); |
908 if (!scanner()->ScanRegExpFlags()) { | 1008 if (!scanner()->ScanRegExpFlags()) { |
909 Next(); | 1009 Next(); |
910 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); | 1010 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); |
911 *ok = false; | 1011 *ok = false; |
912 return Traits::EmptyExpression(); | 1012 return Traits::EmptyExpression(); |
913 } | 1013 } |
914 typename Traits::IdentifierType js_flags = this->NextLiteralString(TENURED); | 1014 typename Traits::Type::Identifier js_flags = |
| 1015 this->NextLiteralString(TENURED); |
915 Next(); | 1016 Next(); |
916 return this->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); | 1017 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); |
917 } | 1018 } |
918 | 1019 |
919 | 1020 |
920 template <typename Traits> | 1021 template <typename Traits> |
921 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | 1022 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( |
922 Token::Value property, | 1023 Token::Value property, |
923 PropertyKind type, | 1024 PropertyKind type, |
924 bool* ok) { | 1025 bool* ok) { |
925 int old; | 1026 int old; |
926 if (property == Token::NUMBER) { | 1027 if (property == Token::NUMBER) { |
(...skipping 21 matching lines...) Expand all Loading... |
948 "accessor_get_set"); | 1049 "accessor_get_set"); |
949 } | 1050 } |
950 *ok = false; | 1051 *ok = false; |
951 } | 1052 } |
952 } | 1053 } |
953 | 1054 |
954 | 1055 |
955 } } // v8::internal | 1056 } } // v8::internal |
956 | 1057 |
957 #endif // V8_PREPARSER_H | 1058 #endif // V8_PREPARSER_H |
OLD | NEW |