OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
7 | 7 |
8 #include "src/bailout-reason.h" | 8 #include "src/bailout-reason.h" |
9 #include "src/expression-classifier.h" | 9 #include "src/expression-classifier.h" |
10 #include "src/func-name-inferrer.h" | 10 #include "src/func-name-inferrer.h" |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
647 | 647 |
648 void FormalParameterInitializerUnexpectedToken( | 648 void FormalParameterInitializerUnexpectedToken( |
649 ExpressionClassifier* classifier) { | 649 ExpressionClassifier* classifier) { |
650 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | 650 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; |
651 const char* arg; | 651 const char* arg; |
652 GetUnexpectedTokenMessage(peek(), &message, &arg); | 652 GetUnexpectedTokenMessage(peek(), &message, &arg); |
653 classifier->RecordFormalParameterInitializerError( | 653 classifier->RecordFormalParameterInitializerError( |
654 scanner()->peek_location(), message, arg); | 654 scanner()->peek_location(), message, arg); |
655 } | 655 } |
656 | 656 |
657 bool IsNextEscapedReservedWord() { | |
658 return scanner()->IsNextEscapedReservedWord( | |
659 language_mode(), this->is_generator(), allow_harmony_sloppy_let()); | |
caitp (gmail)
2015/11/03 17:19:12
It would be really helpful if there was an easier
| |
660 } | |
661 | |
662 void CheckNextEscapedKeyword(bool* ok) { | |
663 if (IsNextEscapedReservedWord()) { | |
caitp (gmail)
2015/11/03 17:19:13
Just used to shrink a bit of code in parser.cc / p
| |
664 ReportMessageAt(scanner()->peek_location(), | |
665 MessageTemplate::kInvalidEscapedReservedWord); | |
666 *ok = false; | |
667 } | |
668 } | |
669 | |
657 // Recursive descent functions: | 670 // Recursive descent functions: |
658 | 671 |
659 // Parses an identifier that is valid for the current scope, in particular it | 672 // Parses an identifier that is valid for the current scope, in particular it |
660 // fails on strict mode future reserved keywords in a strict scope. If | 673 // fails on strict mode future reserved keywords in a strict scope. If |
661 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | 674 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
662 // "arguments" as identifier even in strict mode (this is needed in cases like | 675 // "arguments" as identifier even in strict mode (this is needed in cases like |
663 // "var foo = eval;"). | 676 // "var foo = eval;"). |
664 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); | 677 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); |
665 IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | 678 IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier, |
666 bool* ok); | 679 bool* ok); |
(...skipping 11 matching lines...) Expand all Loading... | |
678 ExpressionClassifier* classifier, bool* ok); | 691 ExpressionClassifier* classifier, bool* ok); |
679 | 692 |
680 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, | 693 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, |
681 bool* ok); | 694 bool* ok); |
682 ExpressionT ParseExpression(bool accept_IN, bool* ok); | 695 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
683 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, | 696 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, |
684 bool* ok); | 697 bool* ok); |
685 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); | 698 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); |
686 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, | 699 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
687 bool* is_static, bool* is_computed_name, | 700 bool* is_static, bool* is_computed_name, |
701 bool* is_identifier, bool* is_escaped_keyword, | |
caitp (gmail)
2015/11/03 17:19:12
I originally wrote a second method for testing thi
| |
688 ExpressionClassifier* classifier, bool* ok); | 702 ExpressionClassifier* classifier, bool* ok); |
689 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); | 703 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); |
690 ObjectLiteralPropertyT ParsePropertyDefinition( | 704 ObjectLiteralPropertyT ParsePropertyDefinition( |
691 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | 705 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, |
692 bool is_static, bool* is_computed_name, bool* has_seen_constructor, | 706 bool is_static, bool* is_computed_name, bool* has_seen_constructor, |
693 ExpressionClassifier* classifier, bool* ok); | 707 ExpressionClassifier* classifier, bool* ok); |
694 typename Traits::Type::ExpressionList ParseArguments( | 708 typename Traits::Type::ExpressionList ParseArguments( |
695 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, | 709 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, |
696 bool* ok); | 710 bool* ok); |
697 ExpressionT ParseAssignmentExpression(bool accept_IN, | 711 ExpressionT ParseAssignmentExpression(bool accept_IN, |
(...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2261 case Token::SMI: | 2275 case Token::SMI: |
2262 case Token::NUMBER: | 2276 case Token::NUMBER: |
2263 classifier->RecordBindingPatternError( | 2277 classifier->RecordBindingPatternError( |
2264 scanner()->peek_location(), MessageTemplate::kUnexpectedTokenNumber); | 2278 scanner()->peek_location(), MessageTemplate::kUnexpectedTokenNumber); |
2265 Next(); | 2279 Next(); |
2266 result = | 2280 result = |
2267 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); | 2281 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); |
2268 break; | 2282 break; |
2269 | 2283 |
2270 case Token::IDENTIFIER: | 2284 case Token::IDENTIFIER: |
2285 if (IsNextEscapedReservedWord()) { | |
caitp (gmail)
2015/11/03 17:19:12
IdentifierReference --- Escaped reserved words are
| |
2286 classifier->RecordExpressionError( | |
2287 scanner()->peek_location(), | |
2288 MessageTemplate::kInvalidEscapedReservedWord); | |
2289 classifier->RecordBindingPatternError( | |
2290 scanner()->peek_location(), | |
2291 MessageTemplate::kInvalidEscapedReservedWord); | |
2292 } | |
2271 case Token::LET: | 2293 case Token::LET: |
2272 case Token::STATIC: | 2294 case Token::STATIC: |
2273 case Token::YIELD: | 2295 case Token::YIELD: |
2274 case Token::FUTURE_STRICT_RESERVED_WORD: { | 2296 case Token::FUTURE_STRICT_RESERVED_WORD: { |
2275 // Using eval or arguments in this context is OK even in strict mode. | 2297 // Using eval or arguments in this context is OK even in strict mode. |
2276 IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); | 2298 IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); |
2277 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, | 2299 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, |
2278 factory()); | 2300 factory()); |
2279 break; | 2301 break; |
2280 } | 2302 } |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2540 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 2562 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
2541 | 2563 |
2542 return factory()->NewArrayLiteral(values, first_spread_index, literal_index, | 2564 return factory()->NewArrayLiteral(values, first_spread_index, literal_index, |
2543 is_strong(language_mode()), pos); | 2565 is_strong(language_mode()), pos); |
2544 } | 2566 } |
2545 | 2567 |
2546 | 2568 |
2547 template <class Traits> | 2569 template <class Traits> |
2548 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( | 2570 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( |
2549 IdentifierT* name, bool* is_get, bool* is_set, bool* is_static, | 2571 IdentifierT* name, bool* is_get, bool* is_set, bool* is_static, |
2550 bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) { | 2572 bool* is_computed_name, bool* is_id, bool* is_escaped_keyword, |
adamk
2015/11/03 23:00:57
Please keep the "is_identifier" name here as in th
caitp (gmail)
2015/11/04 04:49:24
Done.
| |
2573 ExpressionClassifier* classifier, bool* ok) { | |
2551 Token::Value token = peek(); | 2574 Token::Value token = peek(); |
2552 int pos = peek_position(); | 2575 int pos = peek_position(); |
2553 | 2576 |
2554 // For non computed property names we normalize the name a bit: | 2577 // For non computed property names we normalize the name a bit: |
2555 // | 2578 // |
2556 // "12" -> 12 | 2579 // "12" -> 12 |
2557 // 12.3 -> "12.3" | 2580 // 12.3 -> "12.3" |
2558 // 12.30 -> "12.3" | 2581 // 12.30 -> "12.3" |
2559 // identifier -> "identifier" | 2582 // identifier -> "identifier" |
2560 // | 2583 // |
(...skipping 25 matching lines...) Expand all Loading... | |
2586 ExpressionClassifier::ExpressionProductions); | 2609 ExpressionClassifier::ExpressionProductions); |
2587 Expect(Token::RBRACK, CHECK_OK); | 2610 Expect(Token::RBRACK, CHECK_OK); |
2588 return expression; | 2611 return expression; |
2589 } | 2612 } |
2590 | 2613 |
2591 case Token::STATIC: | 2614 case Token::STATIC: |
2592 *is_static = true; | 2615 *is_static = true; |
2593 | 2616 |
2594 // Fall through. | 2617 // Fall through. |
2595 default: | 2618 default: |
2619 *is_id = true; | |
2620 *is_escaped_keyword = IsNextEscapedReservedWord(); | |
2596 *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK); | 2621 *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK); |
2597 break; | 2622 break; |
2598 } | 2623 } |
2599 | 2624 |
2600 uint32_t index; | 2625 uint32_t index; |
2601 return this->IsArrayIndex(*name, &index) | 2626 return this->IsArrayIndex(*name, &index) |
2602 ? factory()->NewNumberLiteral(index, pos) | 2627 ? factory()->NewNumberLiteral(index, pos) |
2603 : factory()->NewStringLiteral(*name, pos); | 2628 : factory()->NewStringLiteral(*name, pos); |
2604 } | 2629 } |
2605 | 2630 |
2606 | 2631 |
2607 template <class Traits> | 2632 template <class Traits> |
2608 typename ParserBase<Traits>::ObjectLiteralPropertyT | 2633 typename ParserBase<Traits>::ObjectLiteralPropertyT |
2609 ParserBase<Traits>::ParsePropertyDefinition( | 2634 ParserBase<Traits>::ParsePropertyDefinition( |
2610 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | 2635 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, |
2611 bool is_static, bool* is_computed_name, bool* has_seen_constructor, | 2636 bool is_static, bool* is_computed_name, bool* has_seen_constructor, |
2612 ExpressionClassifier* classifier, bool* ok) { | 2637 ExpressionClassifier* classifier, bool* ok) { |
2613 DCHECK(!in_class || is_static || has_seen_constructor != nullptr); | 2638 DCHECK(!in_class || is_static || has_seen_constructor != nullptr); |
2614 ExpressionT value = this->EmptyExpression(); | 2639 ExpressionT value = this->EmptyExpression(); |
2615 IdentifierT name = this->EmptyIdentifier(); | 2640 IdentifierT name = this->EmptyIdentifier(); |
2616 bool is_get = false; | 2641 bool is_get = false; |
2617 bool is_set = false; | 2642 bool is_set = false; |
2618 bool name_is_static = false; | 2643 bool name_is_static = false; |
2619 bool is_generator = Check(Token::MUL); | 2644 bool is_generator = Check(Token::MUL); |
2620 | 2645 |
2621 Token::Value name_token = peek(); | 2646 Token::Value name_token = peek(); |
2622 int next_beg_pos = scanner()->peek_location().beg_pos; | 2647 int next_beg_pos = scanner()->peek_location().beg_pos; |
2623 int next_end_pos = scanner()->peek_location().end_pos; | 2648 int next_end_pos = scanner()->peek_location().end_pos; |
2649 bool is_ident = false; | |
adamk
2015/11/03 23:00:57
Please use "is_identifier" here too for consistenc
caitp (gmail)
2015/11/04 04:49:24
Done.
| |
2650 bool is_escaped_keyword = false; | |
2624 ExpressionT name_expression = ParsePropertyName( | 2651 ExpressionT name_expression = ParsePropertyName( |
2625 &name, &is_get, &is_set, &name_is_static, is_computed_name, classifier, | 2652 &name, &is_get, &is_set, &name_is_static, is_computed_name, &is_ident, |
2653 &is_escaped_keyword, classifier, | |
2626 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2654 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2627 | 2655 |
2628 if (fni_ != nullptr && !*is_computed_name) { | 2656 if (fni_ != nullptr && !*is_computed_name) { |
2629 this->PushLiteralName(fni_, name); | 2657 this->PushLiteralName(fni_, name); |
2630 } | 2658 } |
2631 | 2659 |
2632 if (!in_class && !is_generator) { | 2660 if (!in_class && !is_generator) { |
2633 DCHECK(!is_static); | 2661 DCHECK(!is_static); |
2634 | 2662 |
2635 if (peek() == Token::COLON) { | 2663 if (peek() == Token::COLON) { |
2636 // PropertyDefinition | 2664 // PropertyDefinition |
2637 // PropertyName ':' AssignmentExpression | 2665 // PropertyName ':' AssignmentExpression |
2638 if (!*is_computed_name) { | 2666 if (!*is_computed_name) { |
2639 checker->CheckProperty(name_token, kValueProperty, false, false, | 2667 checker->CheckProperty(name_token, kValueProperty, false, false, |
2640 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2668 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2641 } | 2669 } |
2642 Consume(Token::COLON); | 2670 Consume(Token::COLON); |
2643 value = this->ParseAssignmentExpression( | 2671 value = this->ParseAssignmentExpression( |
2644 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2672 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2645 return factory()->NewObjectLiteralProperty(name_expression, value, false, | 2673 return factory()->NewObjectLiteralProperty(name_expression, value, false, |
2646 *is_computed_name); | 2674 *is_computed_name); |
2647 } | 2675 } |
2648 | 2676 |
2649 if (Token::IsIdentifier(name_token, language_mode(), | 2677 if (is_ident && (peek() == Token::COMMA || peek() == Token::RBRACE || |
2650 this->is_generator()) && | 2678 peek() == Token::ASSIGN)) { |
2651 (peek() == Token::COMMA || peek() == Token::RBRACE || | |
2652 peek() == Token::ASSIGN)) { | |
2653 // PropertyDefinition | 2679 // PropertyDefinition |
2654 // IdentifierReference | 2680 // IdentifierReference |
2655 // CoverInitializedName | 2681 // CoverInitializedName |
2656 // | 2682 // |
2657 // CoverInitializedName | 2683 // CoverInitializedName |
2658 // IdentifierReference Initializer? | 2684 // IdentifierReference Initializer? |
2685 if (!Token::IsIdentifier(name_token, language_mode(), | |
2686 this->is_generator())) { | |
2687 ReportUnexpectedTokenAt(scanner()->location(), name_token); | |
2688 *ok = false; | |
2689 return this->EmptyObjectLiteralProperty(); | |
2690 } | |
2691 if (is_escaped_keyword) { | |
2692 classifier->RecordExpressionError( | |
2693 scanner()->location(), | |
2694 MessageTemplate::kInvalidEscapedReservedWord); | |
2695 classifier->RecordBindingPatternError( | |
2696 scanner()->location(), | |
2697 MessageTemplate::kInvalidEscapedReservedWord); | |
2698 } | |
2659 if (classifier->duplicate_finder() != nullptr && | 2699 if (classifier->duplicate_finder() != nullptr && |
2660 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | 2700 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { |
2661 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | 2701 classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
2662 } | 2702 } |
2663 if (name_token == Token::LET) { | 2703 if (name_token == Token::LET) { |
2664 classifier->RecordLetPatternError( | 2704 classifier->RecordLetPatternError( |
2665 scanner()->location(), MessageTemplate::kLetInLexicalBinding); | 2705 scanner()->location(), MessageTemplate::kLetInLexicalBinding); |
2666 } | 2706 } |
2667 | 2707 |
2668 ExpressionT lhs = this->ExpressionFromIdentifier( | 2708 ExpressionT lhs = this->ExpressionFromIdentifier( |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2731 if (is_get || is_set) { | 2771 if (is_get || is_set) { |
2732 // MethodDefinition (Accessors) | 2772 // MethodDefinition (Accessors) |
2733 // get PropertyName '(' ')' '{' FunctionBody '}' | 2773 // get PropertyName '(' ')' '{' FunctionBody '}' |
2734 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}' | 2774 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}' |
2735 name = this->EmptyIdentifier(); | 2775 name = this->EmptyIdentifier(); |
2736 bool dont_care = false; | 2776 bool dont_care = false; |
2737 name_token = peek(); | 2777 name_token = peek(); |
2738 | 2778 |
2739 name_expression = ParsePropertyName( | 2779 name_expression = ParsePropertyName( |
2740 &name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, | 2780 &name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, |
2741 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2781 &dont_care, &dont_care, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
caitp (gmail)
2015/11/03 17:19:13
MethodDefinitions and accessors use the PropertyNa
| |
2742 | 2782 |
2743 if (!*is_computed_name) { | 2783 if (!*is_computed_name) { |
2744 checker->CheckProperty(name_token, kAccessorProperty, is_static, | 2784 checker->CheckProperty(name_token, kAccessorProperty, is_static, |
2745 is_generator, | 2785 is_generator, |
2746 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2786 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2747 } | 2787 } |
2748 | 2788 |
2749 FunctionKind kind = FunctionKind::kAccessorFunction; | 2789 FunctionKind kind = FunctionKind::kAccessorFunction; |
2750 if (!in_class) kind = WithObjectLiteralBit(kind); | 2790 if (!in_class) kind = WithObjectLiteralBit(kind); |
2751 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( | 2791 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( |
(...skipping 1452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4204 return; | 4244 return; |
4205 } | 4245 } |
4206 has_seen_constructor_ = true; | 4246 has_seen_constructor_ = true; |
4207 return; | 4247 return; |
4208 } | 4248 } |
4209 } | 4249 } |
4210 } // namespace internal | 4250 } // namespace internal |
4211 } // namespace v8 | 4251 } // namespace v8 |
4212 | 4252 |
4213 #endif // V8_PREPARSER_H | 4253 #endif // V8_PREPARSER_H |
OLD | NEW |