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

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: Rebasre + feedback = patch for landing 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 struct Error {
587 Error()
588 : location(Scanner::Location::invalid()),
589 message(nullptr),
590 arg(nullptr) {}
591
592 Scanner::Location location;
593 const char* message;
594 const char* arg;
595
596 bool HasError() const { return location.IsValid(); }
597 };
598
599 ExpressionClassifier() {}
600
601 bool is_valid_expression() const { return !expression_error_.HasError(); }
602
603 bool is_valid_binding_pattern() const {
604 return !binding_pattern_error_.HasError();
605 }
606
607 bool is_valid_assignment_pattern() const {
608 return !assignment_pattern_error_.HasError();
609 }
610
611 const Error& expression_error() const { return expression_error_; }
612
613 const Error& binding_pattern_error() const {
614 return binding_pattern_error_;
615 }
616
617 const Error& assignment_pattern_error() const {
618 return assignment_pattern_error_;
619 }
620
621 void RecordExpressionError(const Scanner::Location& loc,
622 const char* message, const char* arg = nullptr) {
623 if (!is_valid_expression()) return;
624 expression_error_.location = loc;
625 expression_error_.message = message;
626 expression_error_.arg = arg;
627 }
628
629 void RecordBindingPatternError(const Scanner::Location& loc,
630 const char* message,
631 const char* arg = nullptr) {
632 if (!is_valid_binding_pattern()) return;
633 binding_pattern_error_.location = loc;
634 binding_pattern_error_.message = message;
635 binding_pattern_error_.arg = arg;
636 }
637
638 void RecordAssignmentPatternError(const Scanner::Location& loc,
639 const char* message,
640 const char* arg = nullptr) {
641 if (!is_valid_assignment_pattern()) return;
642 assignment_pattern_error_.location = loc;
643 assignment_pattern_error_.message = message;
644 assignment_pattern_error_.arg = arg;
645 }
646
647 private:
648 Error expression_error_;
649 Error binding_pattern_error_;
650 Error assignment_pattern_error_;
651 };
652
653 void ReportClassifierError(
654 const typename ExpressionClassifier::Error& error) {
655 Traits::ReportMessageAt(error.location, error.message, error.arg,
656 kSyntaxError);
657 }
658
659 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) {
660 if (!classifier->is_valid_expression()) {
661 ReportClassifierError(classifier->expression_error());
662 *ok = false;
663 }
664 }
665
666 void ValidateBindingPattern(const ExpressionClassifier* classifier,
667 bool* ok) {
668 if (!classifier->is_valid_binding_pattern()) {
669 ReportClassifierError(classifier->binding_pattern_error());
670 *ok = false;
671 }
672 }
673
674 void ValidateAssignmentPattern(const ExpressionClassifier* classifier,
675 bool* ok) {
676 if (!classifier->is_valid_assignment_pattern()) {
677 ReportClassifierError(classifier->assignment_pattern_error());
678 *ok = false;
679 }
680 }
681
682
584 // Recursive descent functions: 683 // Recursive descent functions:
585 684
586 // Parses an identifier that is valid for the current scope, in particular it 685 // 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 686 // fails on strict mode future reserved keywords in a strict scope. If
588 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or 687 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
589 // "arguments" as identifier even in strict mode (this is needed in cases like 688 // "arguments" as identifier even in strict mode (this is needed in cases like
590 // "var foo = eval;"). 689 // "var foo = eval;").
591 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); 690 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok);
691 IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
692 bool* ok);
592 // Parses an identifier or a strict mode future reserved word, and indicate 693 // Parses an identifier or a strict mode future reserved word, and indicate
593 // whether it is strict mode future reserved. 694 // whether it is strict mode future reserved.
594 IdentifierT ParseIdentifierOrStrictReservedWord( 695 IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
595 bool* is_strict_reserved, 696 bool* ok);
596 bool* ok);
597 IdentifierT ParseIdentifierName(bool* ok); 697 IdentifierT ParseIdentifierName(bool* ok);
598 // Parses an identifier and determines whether or not it is 'get' or 'set'. 698 // Parses an identifier and determines whether or not it is 'get' or 'set'.
599 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, 699 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set,
600 bool* is_set,
601 bool* ok); 700 bool* ok);
602 701
603 702
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, 703 ExpressionT ParseRegExpLiteral(bool seen_equal,
645 ExpressionClassifier* classifier, bool* ok); 704 ExpressionClassifier* classifier, bool* ok);
646 705
647 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, 706 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier,
648 bool* ok); 707 bool* ok);
649 ExpressionT ParseExpression(bool accept_IN, bool* ok); 708 ExpressionT ParseExpression(bool accept_IN, bool* ok);
650 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, 709 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier,
651 bool* ok); 710 bool* ok);
652 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); 711 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok);
653 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, 712 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); 2012 const char* name = Token::String(token);
1954 DCHECK(name != NULL); 2013 DCHECK(name != NULL);
1955 Traits::ReportMessageAt(source_location, "unexpected_token", name); 2014 Traits::ReportMessageAt(source_location, "unexpected_token", name);
1956 } 2015 }
1957 } 2016 }
1958 2017
1959 2018
1960 template <class Traits> 2019 template <class Traits>
1961 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( 2020 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
1962 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { 2021 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) {
2022 ExpressionClassifier classifier;
2023 auto result = ParseAndClassifyIdentifier(&classifier, ok);
2024 if (!*ok) return Traits::EmptyIdentifier();
2025
2026 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) {
2027 ValidateAssignmentPattern(&classifier, ok);
2028 if (!*ok) return Traits::EmptyIdentifier();
2029 ValidateBindingPattern(&classifier, ok);
2030 if (!*ok) return Traits::EmptyIdentifier();
2031 } else {
2032 ValidateExpression(&classifier, ok);
2033 if (!*ok) return Traits::EmptyIdentifier();
2034 }
2035
2036 return result;
2037 }
2038
2039
2040 template <class Traits>
2041 typename ParserBase<Traits>::IdentifierT
2042 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
2043 bool* ok) {
1963 Token::Value next = Next(); 2044 Token::Value next = Next();
1964 if (next == Token::IDENTIFIER) { 2045 if (next == Token::IDENTIFIER) {
1965 IdentifierT name = this->GetSymbol(scanner()); 2046 IdentifierT name = this->GetSymbol(scanner());
1966 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { 2047 if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) {
1967 if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) { 2048 classifier->RecordBindingPatternError(scanner()->location(),
1968 ReportMessage("strict_eval_arguments"); 2049 "strict_eval_arguments");
1969 *ok = false; 2050 }
1970 } 2051 if (is_strong(language_mode()) && this->IsUndefined(name)) {
1971 if (is_strong(language_mode()) && this->IsUndefined(name)) { 2052 // TODO(dslomov): allow 'undefined' in nested patterns.
1972 ReportMessage("strong_undefined"); 2053 classifier->RecordBindingPatternError(scanner()->location(),
1973 *ok = false; 2054 "strong_undefined");
1974 } 2055 classifier->RecordAssignmentPatternError(scanner()->location(),
1975 } else { 2056 "strong_undefined");
1976 if (is_strong(language_mode()) && this->IsArguments(name)) { 2057 }
1977 ReportMessage("strong_arguments"); 2058 if (is_strong(language_mode()) && this->IsArguments(name)) {
1978 *ok = false; 2059 classifier->RecordExpressionError(scanner()->location(),
1979 } 2060 "strong_arguments");
1980 } 2061 }
1981 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); 2062 if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
1982 return name; 2063 return name;
1983 } else if (is_sloppy(language_mode()) && 2064 } else if (is_sloppy(language_mode()) &&
1984 (next == Token::FUTURE_STRICT_RESERVED_WORD || 2065 (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1985 next == Token::LET || next == Token::STATIC || 2066 next == Token::LET || next == Token::STATIC ||
1986 (next == Token::YIELD && !is_generator()))) { 2067 (next == Token::YIELD && !is_generator()))) {
1987 return this->GetSymbol(scanner()); 2068 return this->GetSymbol(scanner());
1988 } else { 2069 } else {
1989 this->ReportUnexpectedToken(next); 2070 this->ReportUnexpectedToken(next);
1990 *ok = false; 2071 *ok = false;
1991 return Traits::EmptyIdentifier(); 2072 return Traits::EmptyIdentifier();
1992 } 2073 }
1993 } 2074 }
1994 2075
2076
1995 template <class Traits> 2077 template <class Traits>
1996 typename ParserBase<Traits>::IdentifierT ParserBase< 2078 typename ParserBase<Traits>::IdentifierT ParserBase<
1997 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, 2079 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
1998 bool* ok) { 2080 bool* ok) {
1999 Token::Value next = Next(); 2081 Token::Value next = Next();
2000 if (next == Token::IDENTIFIER) { 2082 if (next == Token::IDENTIFIER) {
2001 *is_strict_reserved = false; 2083 *is_strict_reserved = false;
2002 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || 2084 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
2003 next == Token::STATIC || 2085 next == Token::STATIC ||
2004 (next == Token::YIELD && !this->is_generator())) { 2086 (next == Token::YIELD && !this->is_generator())) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 result = 2216 result =
2135 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); 2217 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory());
2136 break; 2218 break;
2137 2219
2138 case Token::IDENTIFIER: 2220 case Token::IDENTIFIER:
2139 case Token::LET: 2221 case Token::LET:
2140 case Token::STATIC: 2222 case Token::STATIC:
2141 case Token::YIELD: 2223 case Token::YIELD:
2142 case Token::FUTURE_STRICT_RESERVED_WORD: { 2224 case Token::FUTURE_STRICT_RESERVED_WORD: {
2143 // Using eval or arguments in this context is OK even in strict mode. 2225 // Using eval or arguments in this context is OK even in strict mode.
2144 IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); 2226 IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK);
2145 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, 2227 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_,
2146 factory()); 2228 factory());
2147 break; 2229 break;
2148 } 2230 }
2149 2231
2150 case Token::STRING: { 2232 case Token::STRING: {
2151 Consume(Token::STRING); 2233 Consume(Token::STRING);
2152 result = this->ExpressionFromString(beg_pos, scanner(), factory()); 2234 result = this->ExpressionFromString(beg_pos, scanner(), factory());
2153 break; 2235 break;
2154 } 2236 }
2155 2237
2156 case Token::ASSIGN_DIV: 2238 case Token::ASSIGN_DIV:
2157 result = this->ParseRegExpLiteral(true, classifier, CHECK_OK); 2239 result = this->ParseRegExpLiteral(true, classifier, CHECK_OK);
2158 break; 2240 break;
2159 2241
2160 case Token::DIV: 2242 case Token::DIV:
2161 result = this->ParseRegExpLiteral(false, classifier, CHECK_OK); 2243 result = this->ParseRegExpLiteral(false, classifier, CHECK_OK);
2162 break; 2244 break;
2163 2245
2164 case Token::LBRACK: 2246 case Token::LBRACK:
2165 result = this->ParseArrayLiteral(classifier, CHECK_OK); 2247 result = this->ParseArrayLiteral(classifier, CHECK_OK);
2166 break; 2248 break;
2167 2249
2168 case Token::LBRACE: 2250 case Token::LBRACE:
2169 result = this->ParseObjectLiteral(classifier, CHECK_OK); 2251 result = this->ParseObjectLiteral(classifier, CHECK_OK);
2170 break; 2252 break;
2171 2253
2172 case Token::LPAREN: 2254 case Token::LPAREN:
2173 Consume(Token::LPAREN); 2255 Consume(Token::LPAREN);
2256 classifier->RecordBindingPatternError(scanner()->location(),
2257 "unexpected_token", "(");
2258 classifier->RecordAssignmentPatternError(scanner()->location(),
2259 "unexpected_token", "(");
2174 if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) { 2260 if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) {
2175 // As a primary expression, the only thing that can follow "()" is "=>". 2261 // As a primary expression, the only thing that can follow "()" is "=>".
2176 Scope* scope = this->NewScope(scope_, ARROW_SCOPE); 2262 Scope* scope = this->NewScope(scope_, ARROW_SCOPE);
2177 scope->set_start_position(beg_pos); 2263 scope->set_start_position(beg_pos);
2178 FormalParameterErrorLocations error_locs; 2264 FormalParameterErrorLocations error_locs;
2179 bool has_rest = false; 2265 bool has_rest = false;
2180 result = this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, 2266 result = this->ParseArrowFunctionLiteral(scope, error_locs, has_rest,
2181 classifier, CHECK_OK); 2267 classifier, CHECK_OK);
2182 } else { 2268 } else {
2183 // Heuristically try to detect immediately called functions before 2269 // Heuristically try to detect immediately called functions before
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2234 2320
2235 return result; 2321 return result;
2236 } 2322 }
2237 2323
2238 2324
2239 template <class Traits> 2325 template <class Traits>
2240 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( 2326 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
2241 bool accept_IN, bool* ok) { 2327 bool accept_IN, bool* ok) {
2242 ExpressionClassifier classifier; 2328 ExpressionClassifier classifier;
2243 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); 2329 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK);
2244 // TODO(dslomov): report error if not a valid expression. 2330 ValidateExpression(&classifier, CHECK_OK);
2245 return result; 2331 return result;
2246 } 2332 }
2247 2333
2248 2334
2249 // Precedence = 1 2335 // Precedence = 1
2250 template <class Traits> 2336 template <class Traits>
2251 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( 2337 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
2252 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { 2338 bool accept_IN, ExpressionClassifier* classifier, bool* ok) {
2253 // Expression :: 2339 // Expression ::
2254 // AssignmentExpression 2340 // AssignmentExpression
(...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after
3713 *ok = false; 3799 *ok = false;
3714 return; 3800 return;
3715 } 3801 }
3716 has_seen_constructor_ = true; 3802 has_seen_constructor_ = true;
3717 return; 3803 return;
3718 } 3804 }
3719 } 3805 }
3720 } } // v8::internal 3806 } } // v8::internal
3721 3807
3722 #endif // V8_PREPARSER_H 3808 #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