Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/preparser.h

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

Powered by Google App Engine
This is Rietveld 408576698