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

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: 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
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 {
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
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
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
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
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
OLDNEW
« src/parser.cc ('K') | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698