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 |