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

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