Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 1598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1609 Token::String(Token::LPAREN)); | 1609 Token::String(Token::LPAREN)); |
| 1610 if (pattern_error) ArrowFormalParametersUnexpectedToken(classifier); | 1610 if (pattern_error) ArrowFormalParametersUnexpectedToken(classifier); |
| 1611 Consume(Token::LPAREN); | 1611 Consume(Token::LPAREN); |
| 1612 if (Check(Token::RPAREN)) { | 1612 if (Check(Token::RPAREN)) { |
| 1613 // ()=>x. The continuation that looks for the => is in | 1613 // ()=>x. The continuation that looks for the => is in |
| 1614 // ParseAssignmentExpression. | 1614 // ParseAssignmentExpression. |
| 1615 classifier->RecordExpressionError(scanner()->location(), | 1615 classifier->RecordExpressionError(scanner()->location(), |
| 1616 MessageTemplate::kUnexpectedToken, | 1616 MessageTemplate::kUnexpectedToken, |
| 1617 Token::String(Token::RPAREN)); | 1617 Token::String(Token::RPAREN)); |
| 1618 return factory()->NewEmptyParentheses(beg_pos); | 1618 return factory()->NewEmptyParentheses(beg_pos); |
| 1619 } else if (Check(Token::ELLIPSIS)) { | |
| 1620 // (...x)=>x. The continuation that looks for the => is in | |
| 1621 // ParseAssignmentExpression. | |
| 1622 int ellipsis_pos = position(); | |
| 1623 int expr_pos = peek_position(); | |
| 1624 classifier->RecordExpressionError(scanner()->location(), | |
| 1625 MessageTemplate::kUnexpectedToken, | |
| 1626 Token::String(Token::ELLIPSIS)); | |
| 1627 classifier->RecordNonSimpleParameter(); | |
| 1628 ExpressionClassifier binding_classifier(this); | |
| 1629 // TODO(adamk): The grammar for this is | |
| 1630 // BindingIdentifier | BindingPattern, so | |
| 1631 // ParseAssignmentExpression is overkill. | |
| 1632 ExpressionT expr = | |
| 1633 ParseAssignmentExpression(true, &binding_classifier, CHECK_OK); | |
| 1634 // This already couldn't be an expression or a pattern, so the | |
| 1635 // only remaining possibility is an arrow formal parameter list. | |
| 1636 classifier->Accumulate( | |
| 1637 &binding_classifier, | |
| 1638 ExpressionClassifier::ArrowFormalParametersProduction); | |
| 1639 if (!impl()->IsIdentifier(expr) && !IsValidPattern(expr)) { | |
| 1640 classifier->RecordArrowFormalParametersError( | |
| 1641 Scanner::Location(ellipsis_pos, scanner()->location().end_pos), | |
| 1642 MessageTemplate::kInvalidRestParameter); | |
| 1643 } | |
| 1644 if (peek() == Token::COMMA) { | |
| 1645 impl()->ReportMessageAt(scanner()->peek_location(), | |
| 1646 MessageTemplate::kParamAfterRest); | |
| 1647 *ok = false; | |
| 1648 return impl()->EmptyExpression(); | |
| 1649 } | |
| 1650 Expect(Token::RPAREN, CHECK_OK); | |
| 1651 return factory()->NewSpread(expr, ellipsis_pos, expr_pos); | |
| 1652 } | 1619 } |
| 1653 // Heuristically try to detect immediately called functions before | 1620 // Heuristically try to detect immediately called functions before |
| 1654 // seeing the call parentheses. | 1621 // seeing the call parentheses. |
| 1655 function_state_->set_next_function_is_parenthesized(peek() == | 1622 function_state_->set_next_function_is_parenthesized(peek() == |
| 1656 Token::FUNCTION); | 1623 Token::FUNCTION); |
| 1657 ExpressionT expr = ParseExpression(true, classifier, CHECK_OK); | 1624 ExpressionT expr = ParseExpression(true, classifier, CHECK_OK); |
| 1658 Expect(Token::RPAREN, CHECK_OK); | 1625 Expect(Token::RPAREN, CHECK_OK); |
| 1659 return expr; | 1626 return expr; |
| 1660 } | 1627 } |
| 1661 | 1628 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1714 return result; | 1681 return result; |
| 1715 } | 1682 } |
| 1716 | 1683 |
| 1717 template <typename Impl> | 1684 template <typename Impl> |
| 1718 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression( | 1685 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression( |
| 1719 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { | 1686 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { |
| 1720 // Expression :: | 1687 // Expression :: |
| 1721 // AssignmentExpression | 1688 // AssignmentExpression |
| 1722 // Expression ',' AssignmentExpression | 1689 // Expression ',' AssignmentExpression |
| 1723 | 1690 |
| 1724 ExpressionT result; | 1691 ExpressionT result = impl()->EmptyExpression(); |
| 1692 while (true) { | |
|
adamk
2016/08/26 20:13:04
The other loop construct that might make sense her
| |
| 1693 CheckNoTailCallExpressions(classifier, CHECK_OK); | |
| 1694 int comma_pos = position(); | |
| 1695 ExpressionClassifier binding_classifier(this); | |
| 1696 ExpressionT right; | |
| 1697 if (Check(Token::ELLIPSIS)) { | |
| 1698 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only | |
| 1699 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a | |
| 1700 // valid expression. | |
| 1701 binding_classifier.RecordExpressionError( | |
| 1702 scanner()->location(), MessageTemplate::kUnexpectedToken, | |
| 1703 Token::String(Token::ELLIPSIS)); | |
| 1704 int ellipsis_pos = position(); | |
| 1705 int pattern_pos = peek_position(); | |
| 1706 ExpressionT pattern = | |
| 1707 ParsePrimaryExpression(&binding_classifier, CHECK_OK); | |
| 1708 ValidateBindingPattern(&binding_classifier, CHECK_OK); | |
| 1709 right = factory()->NewSpread(pattern, ellipsis_pos, pattern_pos); | |
| 1710 } else { | |
| 1711 right = | |
| 1712 ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); | |
| 1713 } | |
| 1714 // No need to accumulate binding pattern-related errors, since | |
| 1715 // an Expression can't be a binding pattern anyway. | |
| 1716 classifier->Accumulate( | |
| 1717 &binding_classifier, | |
| 1718 ExpressionClassifier::AllProductions & | |
| 1719 ~(ExpressionClassifier::BindingPatternProduction | | |
| 1720 ExpressionClassifier::LetPatternProduction)); | |
| 1721 if (!impl()->IsIdentifier(right)) classifier->RecordNonSimpleParameter(); | |
| 1722 if (impl()->IsEmptyExpression(result)) { | |
|
adamk
2016/08/26 20:13:04
This IsEmptyExpression() thing could be replaced b
nickie
2016/08/29 17:21:27
I'm in favor of the IsEmptyExpression, which I alr
| |
| 1723 // First time through the loop. | |
| 1724 result = right; | |
| 1725 } else { | |
| 1726 result = | |
| 1727 factory()->NewBinaryOperation(Token::COMMA, result, right, comma_pos); | |
| 1728 } | |
| 1725 | 1729 |
| 1726 // No need to accumulate binding pattern-related errors, since | 1730 if (!Check(Token::COMMA)) break; |
| 1727 // an Expression can't be a binding pattern anyway. | 1731 |
| 1728 static const unsigned kExpressionProductions = | 1732 if (right->IsSpread()) { |
| 1729 ExpressionClassifier::AllProductions & | |
| 1730 ~(ExpressionClassifier::BindingPatternProduction | | |
| 1731 ExpressionClassifier::LetPatternProduction); | |
| 1732 { | |
| 1733 ExpressionClassifier binding_classifier(this); | |
| 1734 result = | |
| 1735 ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); | |
| 1736 classifier->Accumulate(&binding_classifier, kExpressionProductions); | |
| 1737 } | |
| 1738 bool is_simple_parameter_list = impl()->IsIdentifier(result); | |
| 1739 bool seen_rest = false; | |
| 1740 while (peek() == Token::COMMA) { | |
| 1741 CheckNoTailCallExpressions(classifier, CHECK_OK); | |
| 1742 if (seen_rest) { | |
| 1743 // At this point the production can't possibly be valid, but we don't know | |
| 1744 // which error to signal. | |
| 1745 classifier->RecordArrowFormalParametersError( | 1733 classifier->RecordArrowFormalParametersError( |
| 1746 scanner()->peek_location(), MessageTemplate::kParamAfterRest); | 1734 scanner()->location(), MessageTemplate::kParamAfterRest); |
| 1747 } | 1735 } |
| 1748 Consume(Token::COMMA); | 1736 |
| 1749 bool is_rest = false; | |
| 1750 if (allow_harmony_trailing_commas() && peek() == Token::RPAREN && | 1737 if (allow_harmony_trailing_commas() && peek() == Token::RPAREN && |
| 1751 PeekAhead() == Token::ARROW) { | 1738 PeekAhead() == Token::ARROW) { |
| 1752 // a trailing comma is allowed at the end of an arrow parameter list | 1739 // a trailing comma is allowed at the end of an arrow parameter list |
| 1753 break; | 1740 break; |
| 1754 } else if (peek() == Token::ELLIPSIS) { | |
| 1755 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only | |
| 1756 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a | |
| 1757 // valid expression or binding pattern. | |
| 1758 ExpressionUnexpectedToken(classifier); | |
| 1759 BindingPatternUnexpectedToken(classifier); | |
| 1760 Consume(Token::ELLIPSIS); | |
| 1761 // TODO(adamk): If is_rest is true we don't need to parse an assignment | |
| 1762 // expression, the grammar is BindingIdentifier | BindingPattern. | |
| 1763 seen_rest = is_rest = true; | |
| 1764 } | 1741 } |
| 1765 int pos = position(), expr_pos = peek_position(); | |
| 1766 ExpressionClassifier binding_classifier(this); | |
| 1767 ExpressionT right = | |
| 1768 ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); | |
| 1769 classifier->Accumulate(&binding_classifier, kExpressionProductions); | |
| 1770 if (is_rest) { | |
| 1771 if (!impl()->IsIdentifier(right) && !IsValidPattern(right)) { | |
| 1772 classifier->RecordArrowFormalParametersError( | |
| 1773 Scanner::Location(pos, scanner()->location().end_pos), | |
| 1774 MessageTemplate::kInvalidRestParameter); | |
| 1775 } | |
| 1776 right = factory()->NewSpread(right, pos, expr_pos); | |
| 1777 } | |
| 1778 is_simple_parameter_list = | |
| 1779 is_simple_parameter_list && impl()->IsIdentifier(right); | |
| 1780 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); | |
| 1781 } | |
| 1782 if (!is_simple_parameter_list || seen_rest) { | |
| 1783 classifier->RecordNonSimpleParameter(); | |
| 1784 } | 1742 } |
| 1785 | 1743 |
| 1786 return result; | 1744 return result; |
| 1787 } | 1745 } |
| 1788 | 1746 |
| 1789 template <typename Impl> | 1747 template <typename Impl> |
| 1790 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral( | 1748 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral( |
| 1791 ExpressionClassifier* classifier, bool* ok) { | 1749 ExpressionClassifier* classifier, bool* ok) { |
| 1792 // ArrayLiteral :: | 1750 // ArrayLiteral :: |
| 1793 // '[' Expression? (',' Expression?)* ']' | 1751 // '[' Expression? (',' Expression?)* ']' |
| (...skipping 1895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3689 has_seen_constructor_ = true; | 3647 has_seen_constructor_ = true; |
| 3690 return; | 3648 return; |
| 3691 } | 3649 } |
| 3692 } | 3650 } |
| 3693 | 3651 |
| 3694 | 3652 |
| 3695 } // namespace internal | 3653 } // namespace internal |
| 3696 } // namespace v8 | 3654 } // namespace v8 |
| 3697 | 3655 |
| 3698 #endif // V8_PARSING_PARSER_BASE_H | 3656 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |