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/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
574 | 574 |
575 void ReportMessageAt(Scanner::Location location, const char* message, | 575 void ReportMessageAt(Scanner::Location location, const char* message, |
576 ParseErrorType error_type = kSyntaxError) { | 576 ParseErrorType error_type = kSyntaxError) { |
577 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0), | 577 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0), |
578 error_type); | 578 error_type); |
579 } | 579 } |
580 | 580 |
581 void ReportUnexpectedToken(Token::Value token); | 581 void ReportUnexpectedToken(Token::Value token); |
582 void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token); | 582 void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token); |
583 | 583 |
584 class ExpressionClassifier { | |
585 public: | |
586 ExpressionClassifier() | |
587 : expression_error_(Scanner::Location::invalid()), | |
588 expression_error_message_(nullptr), | |
589 binding_pattern_error_(Scanner::Location::invalid()), | |
590 binding_pattern_error_message_(nullptr), | |
591 assignment_pattern_error_(Scanner::Location::invalid()), | |
592 assignment_pattern_error_message_(nullptr) {} | |
593 | |
594 bool is_valid_expression() const { | |
595 return expression_error_ == Scanner::Location::invalid(); | |
arv (Not doing code reviews)
2015/04/23 16:52:52
return expression_error_.IsValid();
Dmitry Lomov (no reviews)
2015/04/23 17:06:50
Done.
| |
596 } | |
597 | |
598 Scanner::Location expression_error_loc() const { return expression_error_; } | |
599 const char* expression_error_message() const { | |
600 return expression_error_message_; | |
601 } | |
602 | |
603 bool is_valid_binding_pattern() const { | |
604 return binding_pattern_error_ == Scanner::Location::invalid(); | |
605 } | |
606 Scanner::Location binding_pattern_error_loc() const { | |
607 return binding_pattern_error_; | |
608 } | |
609 const char* binding_pattern_error_message() const { | |
610 return binding_pattern_error_message_; | |
611 } | |
612 | |
613 bool is_valid_assignment_pattern() const { | |
614 return assignment_pattern_error_ == Scanner::Location::invalid(); | |
615 } | |
616 Scanner::Location assignment_pattern_error_loc() const { | |
617 return assignment_pattern_error_; | |
618 } | |
619 const char* assignment_pattern_error_message() const { | |
620 return assignment_pattern_error_message_; | |
621 } | |
622 | |
623 void RecordExpressionError(const Scanner::Location& loc, | |
624 const char* message) { | |
625 if (!is_valid_expression()) return; | |
626 expression_error_ = loc; | |
627 expression_error_message_ = message; | |
628 } | |
629 | |
630 void RecordBindingPatternError(const Scanner::Location& loc, | |
631 const char* message) { | |
632 if (!is_valid_binding_pattern()) return; | |
633 binding_pattern_error_ = loc; | |
634 binding_pattern_error_message_ = message; | |
635 } | |
636 | |
637 void RecordAssignmentPatternError(const Scanner::Location& loc, | |
638 const char* message) { | |
639 if (!is_valid_assignment_pattern()) return; | |
640 assignment_pattern_error_ = loc; | |
641 assignment_pattern_error_message_ = message; | |
642 } | |
643 | |
644 private: | |
645 Scanner::Location expression_error_; | |
646 const char* expression_error_message_; | |
647 Scanner::Location binding_pattern_error_; | |
648 const char* binding_pattern_error_message_; | |
649 Scanner::Location assignment_pattern_error_; | |
650 const char* assignment_pattern_error_message_; | |
651 }; | |
652 | |
653 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) { | |
654 if (!classifier->is_valid_expression()) { | |
655 ReportMessageAt(classifier->expression_error_loc(), | |
656 classifier->expression_error_message()); | |
657 *ok = false; | |
658 } | |
659 } | |
660 | |
661 void ValidateBindingPattern(const ExpressionClassifier* classifier, | |
662 bool* ok) { | |
663 if (!classifier->is_valid_binding_pattern()) { | |
664 Traits::ReportMessageAt(classifier->binding_pattern_error_loc(), | |
665 classifier->binding_pattern_error_message()); | |
666 *ok = false; | |
667 } | |
668 } | |
669 | |
670 | |
671 void ValidateAssignmentPattern(const ExpressionClassifier* classifier, | |
672 bool* ok) { | |
673 if (!classifier->is_valid_assignment_pattern()) { | |
674 Traits::ReportMessageAt(classifier->assignment_pattern_error_loc(), | |
675 classifier->assignment_pattern_error_message()); | |
676 *ok = false; | |
677 } | |
678 } | |
679 | |
680 | |
584 // Recursive descent functions: | 681 // Recursive descent functions: |
585 | 682 |
586 // Parses an identifier that is valid for the current scope, in particular it | 683 // Parses an identifier that is valid for the current scope, in particular it |
587 // fails on strict mode future reserved keywords in a strict scope. If | 684 // fails on strict mode future reserved keywords in a strict scope. If |
588 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | 685 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
589 // "arguments" as identifier even in strict mode (this is needed in cases like | 686 // "arguments" as identifier even in strict mode (this is needed in cases like |
590 // "var foo = eval;"). | 687 // "var foo = eval;"). |
591 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); | 688 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); |
689 IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
690 bool* ok); | |
592 // Parses an identifier or a strict mode future reserved word, and indicate | 691 // Parses an identifier or a strict mode future reserved word, and indicate |
593 // whether it is strict mode future reserved. | 692 // whether it is strict mode future reserved. |
594 IdentifierT ParseIdentifierOrStrictReservedWord( | 693 IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
595 bool* is_strict_reserved, | 694 bool* ok); |
596 bool* ok); | |
597 IdentifierT ParseIdentifierName(bool* ok); | 695 IdentifierT ParseIdentifierName(bool* ok); |
598 // Parses an identifier and determines whether or not it is 'get' or 'set'. | 696 // Parses an identifier and determines whether or not it is 'get' or 'set'. |
599 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, | 697 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set, |
600 bool* is_set, | |
601 bool* ok); | 698 bool* ok); |
602 | 699 |
603 | 700 |
604 class ExpressionClassifier { | |
605 public: | |
606 ExpressionClassifier() | |
607 : expression_error_(Scanner::Location::invalid()), | |
608 binding_pattern_error_(Scanner::Location::invalid()), | |
609 assignment_pattern_error_(Scanner::Location::invalid()) {} | |
610 | |
611 bool is_valid_expression() const { | |
612 return expression_error_ == Scanner::Location::invalid(); | |
613 } | |
614 | |
615 bool is_valid_binding_pattern() const { | |
616 return binding_pattern_error_ == Scanner::Location::invalid(); | |
617 } | |
618 | |
619 bool is_valid_assignmnent_pattern() const { | |
620 return assignment_pattern_error_ == Scanner::Location::invalid(); | |
621 } | |
622 | |
623 void RecordExpressionError(const Scanner::Location& loc) { | |
624 if (!is_valid_expression()) return; | |
625 expression_error_ = loc; | |
626 } | |
627 | |
628 void RecordBindingPatternError(const Scanner::Location& loc) { | |
629 if (!is_valid_binding_pattern()) return; | |
630 binding_pattern_error_ = loc; | |
631 } | |
632 | |
633 void RecordAssignmentPatternError(const Scanner::Location& loc) { | |
634 if (!is_valid_assignmnent_pattern()) return; | |
635 assignment_pattern_error_ = loc; | |
636 } | |
637 | |
638 private: | |
639 Scanner::Location expression_error_; | |
640 Scanner::Location binding_pattern_error_; | |
641 Scanner::Location assignment_pattern_error_; | |
642 }; | |
643 | |
644 ExpressionT ParseRegExpLiteral(bool seen_equal, | 701 ExpressionT ParseRegExpLiteral(bool seen_equal, |
645 ExpressionClassifier* classifier, bool* ok); | 702 ExpressionClassifier* classifier, bool* ok); |
646 | 703 |
647 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, | 704 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, |
648 bool* ok); | 705 bool* ok); |
649 ExpressionT ParseExpression(bool accept_IN, bool* ok); | 706 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
650 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, | 707 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, |
651 bool* ok); | 708 bool* ok); |
652 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); | 709 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); |
653 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, | 710 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1953 const char* name = Token::String(token); | 2010 const char* name = Token::String(token); |
1954 DCHECK(name != NULL); | 2011 DCHECK(name != NULL); |
1955 Traits::ReportMessageAt(source_location, "unexpected_token", name); | 2012 Traits::ReportMessageAt(source_location, "unexpected_token", name); |
1956 } | 2013 } |
1957 } | 2014 } |
1958 | 2015 |
1959 | 2016 |
1960 template <class Traits> | 2017 template <class Traits> |
1961 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( | 2018 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
1962 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { | 2019 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { |
2020 ExpressionClassifier classifier; | |
2021 auto result = ParseAndClassifyIdentifier(&classifier, ok); | |
2022 if (!*ok) return Traits::EmptyIdentifier(); | |
2023 | |
2024 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { | |
2025 ValidateAssignmentPattern(&classifier, ok); | |
2026 if (!*ok) return Traits::EmptyIdentifier(); | |
2027 ValidateBindingPattern(&classifier, ok); | |
2028 if (!*ok) return Traits::EmptyIdentifier(); | |
2029 } else { | |
2030 ValidateExpression(&classifier, ok); | |
2031 if (!*ok) return Traits::EmptyIdentifier(); | |
2032 } | |
2033 | |
2034 return result; | |
2035 } | |
2036 | |
2037 | |
2038 template <class Traits> | |
2039 typename ParserBase<Traits>::IdentifierT | |
2040 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
2041 bool* ok) { | |
1963 Token::Value next = Next(); | 2042 Token::Value next = Next(); |
1964 if (next == Token::IDENTIFIER) { | 2043 if (next == Token::IDENTIFIER) { |
1965 IdentifierT name = this->GetSymbol(scanner()); | 2044 IdentifierT name = this->GetSymbol(scanner()); |
1966 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { | 2045 if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) { |
1967 if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) { | 2046 classifier->RecordBindingPatternError(scanner()->location(), |
1968 ReportMessage("strict_eval_arguments"); | 2047 "strict_eval_arguments"); |
1969 *ok = false; | 2048 } |
1970 } | 2049 if (is_strong(language_mode()) && this->IsUndefined(name)) { |
1971 if (is_strong(language_mode()) && this->IsUndefined(name)) { | 2050 // TODO(dslomov): allow 'undefined' in nested patterns. |
1972 ReportMessage("strong_undefined"); | 2051 classifier->RecordBindingPatternError(scanner()->location(), |
1973 *ok = false; | 2052 "strong_undefined"); |
1974 } | 2053 classifier->RecordAssignmentPatternError(scanner()->location(), |
1975 } else { | 2054 "strong_undefined"); |
1976 if (is_strong(language_mode()) && this->IsArguments(name)) { | 2055 } |
1977 ReportMessage("strong_arguments"); | 2056 if (is_strong(language_mode()) && this->IsArguments(name)) { |
1978 *ok = false; | 2057 classifier->RecordExpressionError(scanner()->location(), |
1979 } | 2058 "strong_arguments"); |
1980 } | 2059 } |
1981 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); | 2060 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); |
1982 return name; | 2061 return name; |
1983 } else if (is_sloppy(language_mode()) && | 2062 } else if (is_sloppy(language_mode()) && |
1984 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 2063 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
1985 next == Token::LET || next == Token::STATIC || | 2064 next == Token::LET || next == Token::STATIC || |
1986 (next == Token::YIELD && !is_generator()))) { | 2065 (next == Token::YIELD && !is_generator()))) { |
1987 return this->GetSymbol(scanner()); | 2066 return this->GetSymbol(scanner()); |
1988 } else { | 2067 } else { |
1989 this->ReportUnexpectedToken(next); | 2068 this->ReportUnexpectedToken(next); |
1990 *ok = false; | 2069 *ok = false; |
1991 return Traits::EmptyIdentifier(); | 2070 return Traits::EmptyIdentifier(); |
1992 } | 2071 } |
1993 } | 2072 } |
1994 | 2073 |
2074 | |
1995 template <class Traits> | 2075 template <class Traits> |
1996 typename ParserBase<Traits>::IdentifierT ParserBase< | 2076 typename ParserBase<Traits>::IdentifierT ParserBase< |
1997 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | 2077 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
1998 bool* ok) { | 2078 bool* ok) { |
1999 Token::Value next = Next(); | 2079 Token::Value next = Next(); |
2000 if (next == Token::IDENTIFIER) { | 2080 if (next == Token::IDENTIFIER) { |
2001 *is_strict_reserved = false; | 2081 *is_strict_reserved = false; |
2002 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || | 2082 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || |
2003 next == Token::STATIC || | 2083 next == Token::STATIC || |
2004 (next == Token::YIELD && !this->is_generator())) { | 2084 (next == Token::YIELD && !this->is_generator())) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2134 result = | 2214 result = |
2135 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); | 2215 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); |
2136 break; | 2216 break; |
2137 | 2217 |
2138 case Token::IDENTIFIER: | 2218 case Token::IDENTIFIER: |
2139 case Token::LET: | 2219 case Token::LET: |
2140 case Token::STATIC: | 2220 case Token::STATIC: |
2141 case Token::YIELD: | 2221 case Token::YIELD: |
2142 case Token::FUTURE_STRICT_RESERVED_WORD: { | 2222 case Token::FUTURE_STRICT_RESERVED_WORD: { |
2143 // Using eval or arguments in this context is OK even in strict mode. | 2223 // Using eval or arguments in this context is OK even in strict mode. |
2144 IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 2224 IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); |
2145 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, | 2225 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, |
2146 factory()); | 2226 factory()); |
2147 break; | 2227 break; |
2148 } | 2228 } |
2149 | 2229 |
2150 case Token::STRING: { | 2230 case Token::STRING: { |
2151 Consume(Token::STRING); | 2231 Consume(Token::STRING); |
2152 result = this->ExpressionFromString(beg_pos, scanner(), factory()); | 2232 result = this->ExpressionFromString(beg_pos, scanner(), factory()); |
2153 break; | 2233 break; |
2154 } | 2234 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2234 | 2314 |
2235 return result; | 2315 return result; |
2236 } | 2316 } |
2237 | 2317 |
2238 | 2318 |
2239 template <class Traits> | 2319 template <class Traits> |
2240 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | 2320 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
2241 bool accept_IN, bool* ok) { | 2321 bool accept_IN, bool* ok) { |
2242 ExpressionClassifier classifier; | 2322 ExpressionClassifier classifier; |
2243 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); | 2323 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); |
2244 // TODO(dslomov): report error if not a valid expression. | 2324 ValidateExpression(&classifier, CHECK_OK); |
2245 return result; | 2325 return result; |
2246 } | 2326 } |
2247 | 2327 |
2248 | 2328 |
2249 // Precedence = 1 | 2329 // Precedence = 1 |
2250 template <class Traits> | 2330 template <class Traits> |
2251 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | 2331 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
2252 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { | 2332 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { |
2253 // Expression :: | 2333 // Expression :: |
2254 // AssignmentExpression | 2334 // AssignmentExpression |
(...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3713 *ok = false; | 3793 *ok = false; |
3714 return; | 3794 return; |
3715 } | 3795 } |
3716 has_seen_constructor_ = true; | 3796 has_seen_constructor_ = true; |
3717 return; | 3797 return; |
3718 } | 3798 } |
3719 } | 3799 } |
3720 } } // v8::internal | 3800 } } // v8::internal |
3721 | 3801 |
3722 #endif // V8_PREPARSER_H | 3802 #endif // V8_PREPARSER_H |
OLD | NEW |