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

Side by Side Diff: src/parsing/parser-base.h

Issue 2271063002: Centralize and standardize logic for ExpressionClassifier accumulation (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased Created 4 years, 3 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_PARSING_PARSER_BASE_H 5 #ifndef V8_PARSING_PARSER_BASE_H
6 #define V8_PARSING_PARSER_BASE_H 6 #define V8_PARSING_PARSER_BASE_H
7 7
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/hashmap.h" 10 #include "src/base/hashmap.h"
(...skipping 1629 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 } else if (Check(Token::ELLIPSIS)) { 1640 } else if (Check(Token::ELLIPSIS)) {
1641 // (...x)=>x. The continuation that looks for the => is in 1641 // (...x)=>x. The continuation that looks for the => is in
1642 // ParseAssignmentExpression. 1642 // ParseAssignmentExpression.
1643 int ellipsis_pos = position(); 1643 int ellipsis_pos = position();
1644 int expr_pos = peek_position(); 1644 int expr_pos = peek_position();
1645 classifier->RecordExpressionError(scanner()->location(), 1645 classifier->RecordExpressionError(scanner()->location(),
1646 MessageTemplate::kUnexpectedToken, 1646 MessageTemplate::kUnexpectedToken,
1647 Token::String(Token::ELLIPSIS)); 1647 Token::String(Token::ELLIPSIS));
1648 classifier->RecordNonSimpleParameter(); 1648 classifier->RecordNonSimpleParameter();
1649 ExpressionClassifier binding_classifier(this); 1649 ExpressionClassifier binding_classifier(this);
1650 // TODO(adamk): The grammar for this is
1651 // BindingIdentifier | BindingPattern, so
1652 // ParseAssignmentExpression is overkill.
1650 ExpressionT expr = this->ParseAssignmentExpression( 1653 ExpressionT expr = this->ParseAssignmentExpression(
1651 true, &binding_classifier, CHECK_OK); 1654 true, &binding_classifier, CHECK_OK);
1652 classifier->Accumulate(&binding_classifier, 1655 // This already couldn't be an expression or a pattern, so the
1653 ExpressionClassifier::AllProductions); 1656 // only remaining possibility is an arrow formal parameter list.
1657 classifier->Accumulate(
1658 &binding_classifier,
1659 ExpressionClassifier::ArrowFormalParametersProduction);
1654 if (!impl()->IsIdentifier(expr) && !IsValidPattern(expr)) { 1660 if (!impl()->IsIdentifier(expr) && !IsValidPattern(expr)) {
1655 classifier->RecordArrowFormalParametersError( 1661 classifier->RecordArrowFormalParametersError(
1656 Scanner::Location(ellipsis_pos, scanner()->location().end_pos), 1662 Scanner::Location(ellipsis_pos, scanner()->location().end_pos),
1657 MessageTemplate::kInvalidRestParameter); 1663 MessageTemplate::kInvalidRestParameter);
1658 } 1664 }
1659 if (peek() == Token::COMMA) { 1665 if (peek() == Token::COMMA) {
1660 impl()->ReportMessageAt(scanner()->peek_location(), 1666 impl()->ReportMessageAt(scanner()->peek_location(),
1661 MessageTemplate::kParamAfterRest); 1667 MessageTemplate::kParamAfterRest);
1662 *ok = false; 1668 *ok = false;
1663 return impl()->EmptyExpression(); 1669 return impl()->EmptyExpression();
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1730 } 1736 }
1731 1737
1732 template <typename Impl> 1738 template <typename Impl>
1733 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression( 1739 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression(
1734 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { 1740 bool accept_IN, ExpressionClassifier* classifier, bool* ok) {
1735 // Expression :: 1741 // Expression ::
1736 // AssignmentExpression 1742 // AssignmentExpression
1737 // Expression ',' AssignmentExpression 1743 // Expression ',' AssignmentExpression
1738 1744
1739 ExpressionT result; 1745 ExpressionT result;
1746
1747 // No need to accumulate binding pattern-related errors, since
1748 // an Expression can't be a binding pattern anyway.
1749 static const unsigned kExpressionProductions =
1750 ExpressionClassifier::AllProductions &
1751 ~(ExpressionClassifier::BindingPatternProduction |
1752 ExpressionClassifier::LetPatternProduction);
1740 { 1753 {
1741 ExpressionClassifier binding_classifier(this); 1754 ExpressionClassifier binding_classifier(this);
1742 result = this->ParseAssignmentExpression(accept_IN, &binding_classifier, 1755 result = this->ParseAssignmentExpression(accept_IN, &binding_classifier,
1743 CHECK_OK); 1756 CHECK_OK);
1744 classifier->Accumulate(&binding_classifier, 1757 classifier->Accumulate(&binding_classifier, kExpressionProductions);
1745 ExpressionClassifier::AllProductions);
1746 } 1758 }
1747 bool is_simple_parameter_list = impl()->IsIdentifier(result); 1759 bool is_simple_parameter_list = impl()->IsIdentifier(result);
1748 bool seen_rest = false; 1760 bool seen_rest = false;
1749 while (peek() == Token::COMMA) { 1761 while (peek() == Token::COMMA) {
1750 CheckNoTailCallExpressions(classifier, CHECK_OK); 1762 CheckNoTailCallExpressions(classifier, CHECK_OK);
1751 if (seen_rest) { 1763 if (seen_rest) {
1752 // At this point the production can't possibly be valid, but we don't know 1764 // At this point the production can't possibly be valid, but we don't know
1753 // which error to signal. 1765 // which error to signal.
1754 classifier->RecordArrowFormalParametersError( 1766 classifier->RecordArrowFormalParametersError(
1755 scanner()->peek_location(), MessageTemplate::kParamAfterRest); 1767 scanner()->peek_location(), MessageTemplate::kParamAfterRest);
1756 } 1768 }
1757 Consume(Token::COMMA); 1769 Consume(Token::COMMA);
1758 bool is_rest = false; 1770 bool is_rest = false;
1759 if (allow_harmony_trailing_commas() && peek() == Token::RPAREN && 1771 if (allow_harmony_trailing_commas() && peek() == Token::RPAREN &&
1760 PeekAhead() == Token::ARROW) { 1772 PeekAhead() == Token::ARROW) {
1761 // a trailing comma is allowed at the end of an arrow parameter list 1773 // a trailing comma is allowed at the end of an arrow parameter list
1762 break; 1774 break;
1763 } else if (peek() == Token::ELLIPSIS) { 1775 } else if (peek() == Token::ELLIPSIS) {
1764 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only 1776 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
1765 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a 1777 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a
1766 // valid expression or binding pattern. 1778 // valid expression or binding pattern.
1767 ExpressionUnexpectedToken(classifier); 1779 ExpressionUnexpectedToken(classifier);
1768 BindingPatternUnexpectedToken(classifier); 1780 BindingPatternUnexpectedToken(classifier);
1769 Consume(Token::ELLIPSIS); 1781 Consume(Token::ELLIPSIS);
1782 // TODO(adamk): If is_rest is true we don't need to parse an assignment
1783 // expression, the grammar is BindingIdentifier | BindingPattern.
1770 seen_rest = is_rest = true; 1784 seen_rest = is_rest = true;
1771 } 1785 }
1772 int pos = position(), expr_pos = peek_position(); 1786 int pos = position(), expr_pos = peek_position();
1773 ExpressionClassifier binding_classifier(this); 1787 ExpressionClassifier binding_classifier(this);
1774 ExpressionT right = this->ParseAssignmentExpression( 1788 ExpressionT right = this->ParseAssignmentExpression(
1775 accept_IN, &binding_classifier, CHECK_OK); 1789 accept_IN, &binding_classifier, CHECK_OK);
1776 classifier->Accumulate(&binding_classifier, 1790 classifier->Accumulate(&binding_classifier, kExpressionProductions);
1777 ExpressionClassifier::AllProductions);
1778 if (is_rest) { 1791 if (is_rest) {
1779 if (!impl()->IsIdentifier(right) && !IsValidPattern(right)) { 1792 if (!impl()->IsIdentifier(right) && !IsValidPattern(right)) {
1780 classifier->RecordArrowFormalParametersError( 1793 classifier->RecordArrowFormalParametersError(
1781 Scanner::Location(pos, scanner()->location().end_pos), 1794 Scanner::Location(pos, scanner()->location().end_pos),
1782 MessageTemplate::kInvalidRestParameter); 1795 MessageTemplate::kInvalidRestParameter);
1783 } 1796 }
1784 right = factory()->NewSpread(right, pos, expr_pos); 1797 right = factory()->NewSpread(right, pos, expr_pos);
1785 } 1798 }
1786 is_simple_parameter_list = 1799 is_simple_parameter_list =
1787 is_simple_parameter_list && impl()->IsIdentifier(right); 1800 is_simple_parameter_list && impl()->IsIdentifier(right);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1902 *name = this->GetNumberAsSymbol(scanner()); 1915 *name = this->GetNumberAsSymbol(scanner());
1903 break; 1916 break;
1904 1917
1905 case Token::LBRACK: { 1918 case Token::LBRACK: {
1906 *is_computed_name = true; 1919 *is_computed_name = true;
1907 Consume(Token::LBRACK); 1920 Consume(Token::LBRACK);
1908 ExpressionClassifier computed_name_classifier(this); 1921 ExpressionClassifier computed_name_classifier(this);
1909 ExpressionT expression = 1922 ExpressionT expression =
1910 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); 1923 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK);
1911 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); 1924 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK);
1912 classifier->Accumulate(&computed_name_classifier, 1925 classifier->AccumulateFormalParameterContainmentErrors(
1913 ExpressionClassifier::ExpressionProductions); 1926 &computed_name_classifier);
1914 Expect(Token::RBRACK, CHECK_OK); 1927 Expect(Token::RBRACK, CHECK_OK);
1915 return expression; 1928 return expression;
1916 } 1929 }
1917 1930
1918 default: 1931 default:
1919 *name = ParseIdentifierName(CHECK_OK); 1932 *name = ParseIdentifierName(CHECK_OK);
1920 scanner()->IsGetOrSet(is_get, is_set); 1933 scanner()->IsGetOrSet(is_get, is_set);
1921 break; 1934 break;
1922 } 1935 }
1923 1936
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2017 CheckDestructuringElement(lhs, classifier, next_beg_pos, next_end_pos); 2030 CheckDestructuringElement(lhs, classifier, next_beg_pos, next_end_pos);
2018 2031
2019 ExpressionT value; 2032 ExpressionT value;
2020 if (peek() == Token::ASSIGN) { 2033 if (peek() == Token::ASSIGN) {
2021 Consume(Token::ASSIGN); 2034 Consume(Token::ASSIGN);
2022 ExpressionClassifier rhs_classifier(this); 2035 ExpressionClassifier rhs_classifier(this);
2023 ExpressionT rhs = this->ParseAssignmentExpression( 2036 ExpressionT rhs = this->ParseAssignmentExpression(
2024 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2037 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2025 impl()->RewriteNonPattern(&rhs_classifier, 2038 impl()->RewriteNonPattern(&rhs_classifier,
2026 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2039 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2027 classifier->Accumulate(&rhs_classifier, 2040 classifier->AccumulateFormalParameterContainmentErrors(&rhs_classifier);
2028 ExpressionClassifier::ExpressionProductions);
2029 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, 2041 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
2030 kNoSourcePosition); 2042 kNoSourcePosition);
2031 classifier->RecordObjectLiteralError( 2043 classifier->RecordObjectLiteralError(
2032 Scanner::Location(next_beg_pos, scanner()->location().end_pos), 2044 Scanner::Location(next_beg_pos, scanner()->location().end_pos),
2033 MessageTemplate::kInvalidCoverInitializedName); 2045 MessageTemplate::kInvalidCoverInitializedName);
2034 2046
2035 Traits::SetFunctionNameFromIdentifierRef(rhs, lhs); 2047 Traits::SetFunctionNameFromIdentifierRef(rhs, lhs);
2036 } else { 2048 } else {
2037 value = lhs; 2049 value = lhs;
2038 } 2050 }
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
2387 if (fni_ != nullptr) fni_->Infer(); 2399 if (fni_ != nullptr) fni_->Infer();
2388 2400
2389 return expression; 2401 return expression;
2390 } 2402 }
2391 2403
2392 // "expression" was not itself an arrow function parameter list, but it might 2404 // "expression" was not itself an arrow function parameter list, but it might
2393 // form part of one. Propagate speculative formal parameter error locations 2405 // form part of one. Propagate speculative formal parameter error locations
2394 // (including those for binding patterns, since formal parameters can 2406 // (including those for binding patterns, since formal parameters can
2395 // themselves contain binding patterns). 2407 // themselves contain binding patterns).
2396 // Do not merge pending non-pattern expressions yet! 2408 // Do not merge pending non-pattern expressions yet!
2397 unsigned productions = 2409 unsigned productions = ExpressionClassifier::AllProductions &
2398 ExpressionClassifier::FormalParametersProductions | 2410 ~ExpressionClassifier::ArrowFormalParametersProduction;
2399 ExpressionClassifier::AsyncArrowFormalParametersProduction |
2400 ExpressionClassifier::FormalParameterInitializerProduction;
2401 2411
2402 // Parenthesized identifiers and property references are allowed as part 2412 // Parenthesized identifiers and property references are allowed as part
2403 // of a larger binding pattern, even though parenthesized patterns 2413 // of a larger assignment pattern, even though parenthesized patterns
2404 // themselves are not allowed, e.g., "[(x)] = []". Only accumulate 2414 // themselves are not allowed, e.g., "[(x)] = []". Only accumulate
2405 // assignment pattern errors if the parsed expression is more complex. 2415 // assignment pattern errors if the parsed expression is more complex.
2406 if (IsValidReferenceExpression(expression)) { 2416 if (IsValidReferenceExpression(expression)) {
2407 productions |= ExpressionClassifier::PatternProductions & 2417 productions &= ~ExpressionClassifier::AssignmentPatternProduction;
2408 ~ExpressionClassifier::AssignmentPatternProduction;
2409 } else {
2410 productions |= ExpressionClassifier::PatternProductions;
2411 } 2418 }
2412 2419
2413 const bool is_destructuring_assignment = 2420 const bool is_destructuring_assignment =
2414 IsValidPattern(expression) && peek() == Token::ASSIGN; 2421 IsValidPattern(expression) && peek() == Token::ASSIGN;
2415 if (!is_destructuring_assignment) { 2422 if (is_destructuring_assignment) {
2416 // This may be an expression or a pattern, so we must continue to 2423 // This is definitely not an expression so don't accumulate
2417 // accumulate expression-related errors. 2424 // expression-related errors.
2418 productions |= ExpressionClassifier::ExpressionProductions | 2425 productions &= ~(ExpressionClassifier::ExpressionProduction |
2419 ExpressionClassifier::ObjectLiteralProduction; 2426 ExpressionClassifier::ObjectLiteralProduction |
2427 ExpressionClassifier::TailCallExpressionProduction);
2420 } 2428 }
2421 2429
2422 classifier->Accumulate(&arrow_formals_classifier, productions, false); 2430 classifier->Accumulate(&arrow_formals_classifier, productions, false);
2423 2431
2424 if (!Token::IsAssignmentOp(peek())) { 2432 if (!Token::IsAssignmentOp(peek())) {
2425 // Parsed conditional expression only (no assignment). 2433 // Parsed conditional expression only (no assignment).
2426 // Now pending non-pattern expressions must be merged. 2434 // Now pending non-pattern expressions must be merged.
2427 classifier->MergeNonPatterns(&arrow_formals_classifier); 2435 classifier->MergeNonPatterns(&arrow_formals_classifier);
2428 return expression; 2436 return expression;
2429 } 2437 }
(...skipping 20 matching lines...) Expand all
2450 Token::String(op)); 2458 Token::String(op));
2451 } 2459 }
2452 int pos = position(); 2460 int pos = position();
2453 2461
2454 ExpressionClassifier rhs_classifier(this); 2462 ExpressionClassifier rhs_classifier(this);
2455 2463
2456 ExpressionT right = 2464 ExpressionT right =
2457 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); 2465 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK);
2458 CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK); 2466 CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK);
2459 impl()->RewriteNonPattern(&rhs_classifier, CHECK_OK); 2467 impl()->RewriteNonPattern(&rhs_classifier, CHECK_OK);
2460 classifier->Accumulate( 2468 classifier->AccumulateFormalParameterContainmentErrors(&rhs_classifier);
2461 &rhs_classifier,
2462 ExpressionClassifier::ExpressionProductions |
2463 ExpressionClassifier::ObjectLiteralProduction |
2464 ExpressionClassifier::AsyncArrowFormalParametersProduction);
2465 2469
2466 // TODO(1231235): We try to estimate the set of properties set by 2470 // TODO(1231235): We try to estimate the set of properties set by
2467 // constructors. We define a new property whenever there is an 2471 // constructors. We define a new property whenever there is an
2468 // assignment to a property of 'this'. We should probably only add 2472 // assignment to a property of 'this'. We should probably only add
2469 // properties if we haven't seen them before. Otherwise we'll 2473 // properties if we haven't seen them before. Otherwise we'll
2470 // probably overestimate the number of properties. 2474 // probably overestimate the number of properties.
2471 if (op == Token::ASSIGN && impl()->IsThisProperty(expression)) { 2475 if (op == Token::ASSIGN && impl()->IsThisProperty(expression)) {
2472 function_state_->AddProperty(); 2476 function_state_->AddProperty();
2473 } 2477 }
2474 2478
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
2891 *ok = false; 2895 *ok = false;
2892 return impl()->EmptyExpression(); 2896 return impl()->EmptyExpression();
2893 } 2897 }
2894 if (args->length()) { 2898 if (args->length()) {
2895 // async ( Arguments ) => ... 2899 // async ( Arguments ) => ...
2896 return Traits::ExpressionListToExpression(args); 2900 return Traits::ExpressionListToExpression(args);
2897 } 2901 }
2898 // async () => ... 2902 // async () => ...
2899 return factory()->NewEmptyParentheses(pos); 2903 return factory()->NewEmptyParentheses(pos);
2900 } else { 2904 } else {
2901 classifier->Accumulate(&async_classifier, 2905 classifier->AccumulateFormalParameterContainmentErrors(
2902 ExpressionClassifier::AllProductions); 2906 &async_classifier);
2903 } 2907 }
2904 } else { 2908 } else {
2905 args = ParseArguments(&spread_pos, false, classifier, CHECK_OK); 2909 args = ParseArguments(&spread_pos, false, classifier, CHECK_OK);
2906 } 2910 }
2907 2911
2908 ArrowFormalParametersUnexpectedToken(classifier); 2912 ArrowFormalParametersUnexpectedToken(classifier);
2909 2913
2910 // Keep track of eval() calls since they disable all local variable 2914 // Keep track of eval() calls since they disable all local variable
2911 // optimizations. 2915 // optimizations.
2912 // The calls that need special treatment are the 2916 // The calls that need special treatment are the
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
3716 has_seen_constructor_ = true; 3720 has_seen_constructor_ = true;
3717 return; 3721 return;
3718 } 3722 }
3719 } 3723 }
3720 3724
3721 3725
3722 } // namespace internal 3726 } // namespace internal
3723 } // namespace v8 3727 } // namespace v8
3724 3728
3725 #endif // V8_PARSING_PARSER_BASE_H 3729 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698