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

Side by Side Diff: src/parsing/parser.cc

Issue 2323763002: [parser] Refactor of Parse*Statement*, part 4 (Closed)
Patch Set: Rebase 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
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('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 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 1602 matching lines...) Expand 10 before | Expand all | Expand 10 after
1613 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { 1613 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
1614 SloppyBlockFunctionStatement* delegate = 1614 SloppyBlockFunctionStatement* delegate =
1615 factory()->NewSloppyBlockFunctionStatement(scope()); 1615 factory()->NewSloppyBlockFunctionStatement(scope());
1616 DeclarationScope* target_scope = GetDeclarationScope(); 1616 DeclarationScope* target_scope = GetDeclarationScope();
1617 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); 1617 target_scope->DeclareSloppyBlockFunction(variable_name, delegate);
1618 return delegate; 1618 return delegate;
1619 } 1619 }
1620 return factory()->NewEmptyStatement(kNoSourcePosition); 1620 return factory()->NewEmptyStatement(kNoSourcePosition);
1621 } 1621 }
1622 1622
1623 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, 1623 ZoneList<const AstRawString*>* Parser::DeclareLabel(
1624 const AstRawString* label) { 1624 ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) {
1625 DCHECK(label != NULL); 1625 const AstRawString* label = var->raw_name();
1626 if (labels != NULL) { 1626 // TODO(1240780): We don't check for redeclaration of labels
1627 for (int i = labels->length(); i-- > 0; ) { 1627 // during preparsing since keeping track of the set of active
1628 if (labels->at(i) == label) { 1628 // labels requires nontrivial changes to the way scopes are
1629 return true; 1629 // structured. However, these are probably changes we want to
1630 } 1630 // make later anyway so we should go back and fix this then.
1631 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1632 ReportMessage(MessageTemplate::kLabelRedeclaration, label);
1633 *ok = false;
1634 return nullptr;
1635 }
1636 if (labels == nullptr) {
1637 labels = new (zone()) ZoneList<const AstRawString*>(1, zone());
1638 }
1639 labels->Add(label, zone());
1640 // Remove the "ghost" variable that turned out to be a label
1641 // from the top scope. This way, we don't try to resolve it
1642 // during the scope processing.
1643 scope()->RemoveUnresolved(var);
1644 return labels;
1645 }
1646
1647 bool Parser::ContainsLabel(ZoneList<const AstRawString*>* labels,
1648 const AstRawString* label) {
1649 DCHECK_NOT_NULL(label);
1650 if (labels != nullptr) {
1651 for (int i = labels->length(); i-- > 0;) {
1652 if (labels->at(i) == label) return true;
1631 } 1653 }
1632 } 1654 }
1633 return false; 1655 return false;
1634 } 1656 }
1635 1657
1658 Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
1659 if (IsSubclassConstructor(function_state_->kind())) {
1660 // For subclass constructors we need to return this in case of undefined
1661 // return a Smi (transformed into an exception in the ConstructStub)
1662 // for a non object.
1663 //
1664 // return expr;
1665 //
1666 // Is rewritten as:
1667 //
1668 // return (temp = expr) === undefined ? this :
1669 // %_IsJSReceiver(temp) ? temp : 1;
1670
1671 // temp = expr
1672 Variable* temp = NewTemporary(ast_value_factory()->empty_string());
1673 Assignment* assign = factory()->NewAssignment(
1674 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
1675
1676 // %_IsJSReceiver(temp)
1677 ZoneList<Expression*>* is_spec_object_args =
1678 new (zone()) ZoneList<Expression*>(1, zone());
1679 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
1680 Expression* is_spec_object_call = factory()->NewCallRuntime(
1681 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
1682
1683 // %_IsJSReceiver(temp) ? temp : 1;
1684 Expression* is_object_conditional = factory()->NewConditional(
1685 is_spec_object_call, factory()->NewVariableProxy(temp),
1686 factory()->NewSmiLiteral(1, pos), pos);
1687
1688 // temp === undefined
1689 Expression* is_undefined = factory()->NewCompareOperation(
1690 Token::EQ_STRICT, assign,
1691 factory()->NewUndefinedLiteral(kNoSourcePosition), pos);
1692
1693 // is_undefined ? this : is_object_conditional
1694 return_value = factory()->NewConditional(is_undefined, ThisExpression(pos),
1695 is_object_conditional, pos);
1696 }
1697 if (is_generator()) {
1698 return_value = BuildIteratorResult(return_value, true);
1699 } else if (is_async_function()) {
1700 return_value = BuildResolvePromise(return_value, return_value->position());
1701 }
1702 return return_value;
1703 }
1704
1636 Statement* Parser::ParseFunctionDeclaration(bool* ok) { 1705 Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1637 Consume(Token::FUNCTION); 1706 Consume(Token::FUNCTION);
1638 int pos = position(); 1707 int pos = position();
1639 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; 1708 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
1640 if (Check(Token::MUL)) { 1709 if (Check(Token::MUL)) {
1641 flags |= ParseFunctionFlags::kIsGenerator; 1710 flags |= ParseFunctionFlags::kIsGenerator;
1642 if (allow_harmony_restrictive_declarations()) { 1711 if (allow_harmony_restrictive_declarations()) {
1643 ReportMessageAt(scanner()->location(), 1712 ReportMessageAt(scanner()->location(),
1644 MessageTemplate::kGeneratorInLegacyContext); 1713 MessageTemplate::kGeneratorInLegacyContext);
1645 *ok = false; 1714 *ok = false;
1646 return nullptr; 1715 return nullptr;
1647 } 1716 }
1648 } 1717 }
1649 1718
1650 return ParseHoistableDeclaration(pos, flags, nullptr, false, CHECK_OK); 1719 return ParseHoistableDeclaration(pos, flags, nullptr, false, CHECK_OK);
1651 } 1720 }
1652 1721
1653 Statement* Parser::ParseExpressionOrLabelledStatement(
1654 ZoneList<const AstRawString*>* labels,
1655 AllowLabelledFunctionStatement allow_function, bool* ok) {
1656 // ExpressionStatement | LabelledStatement ::
1657 // Expression ';'
1658 // Identifier ':' Statement
1659 //
1660 // ExpressionStatement[Yield] :
1661 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ;
1662
1663 int pos = peek_position();
1664
1665 switch (peek()) {
1666 case Token::FUNCTION:
1667 case Token::LBRACE:
1668 UNREACHABLE(); // Always handled by the callers.
1669 case Token::CLASS:
1670 ReportUnexpectedToken(Next());
1671 *ok = false;
1672 return nullptr;
1673 default:
1674 break;
1675 }
1676
1677 bool starts_with_idenfifier = peek_any_identifier();
1678 Expression* expr = ParseExpression(true, CHECK_OK);
1679 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
1680 expr->AsVariableProxy() != NULL &&
1681 !expr->AsVariableProxy()->is_this()) {
1682 // Expression is a single identifier, and not, e.g., a parenthesized
1683 // identifier.
1684 VariableProxy* var = expr->AsVariableProxy();
1685 const AstRawString* label = var->raw_name();
1686 // TODO(1240780): We don't check for redeclaration of labels
1687 // during preparsing since keeping track of the set of active
1688 // labels requires nontrivial changes to the way scopes are
1689 // structured. However, these are probably changes we want to
1690 // make later anyway so we should go back and fix this then.
1691 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1692 ReportMessage(MessageTemplate::kLabelRedeclaration, label);
1693 *ok = false;
1694 return NULL;
1695 }
1696 if (labels == NULL) {
1697 labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
1698 }
1699 labels->Add(label, zone());
1700 // Remove the "ghost" variable that turned out to be a label
1701 // from the top scope. This way, we don't try to resolve it
1702 // during the scope processing.
1703 scope()->RemoveUnresolved(var);
1704 Expect(Token::COLON, CHECK_OK);
1705 // ES#sec-labelled-function-declarations Labelled Function Declarations
1706 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
1707 if (allow_function == kAllowLabelledFunctionStatement) {
1708 return ParseFunctionDeclaration(ok);
1709 } else {
1710 return ParseScopedStatement(labels, true, ok);
1711 }
1712 }
1713 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
1714 }
1715
1716 // If we have an extension, we allow a native function declaration.
1717 // A native function declaration starts with "native function" with
1718 // no line-terminator between the two words.
1719 if (extension_ != NULL && peek() == Token::FUNCTION &&
1720 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
1721 expr->AsVariableProxy() != NULL &&
1722 expr->AsVariableProxy()->raw_name() ==
1723 ast_value_factory()->native_string() &&
1724 !scanner()->literal_contains_escapes()) {
1725 return ParseNativeDeclaration(ok);
1726 }
1727
1728 // Parsed expression statement, followed by semicolon.
1729 ExpectSemicolon(CHECK_OK);
1730 return factory()->NewExpressionStatement(expr, pos);
1731 }
1732
1733
1734 IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
1735 bool* ok) {
1736 // IfStatement ::
1737 // 'if' '(' Expression ')' Statement ('else' Statement)?
1738
1739 int pos = peek_position();
1740 Expect(Token::IF, CHECK_OK);
1741 Expect(Token::LPAREN, CHECK_OK);
1742 Expression* condition = ParseExpression(true, CHECK_OK);
1743 Expect(Token::RPAREN, CHECK_OK);
1744 Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK);
1745 Statement* else_statement = NULL;
1746 if (peek() == Token::ELSE) {
1747 Next();
1748 else_statement = ParseScopedStatement(labels, false, CHECK_OK);
1749 } else {
1750 else_statement = factory()->NewEmptyStatement(kNoSourcePosition);
1751 }
1752 return factory()->NewIfStatement(
1753 condition, then_statement, else_statement, pos);
1754 }
1755
1756
1757 Statement* Parser::ParseContinueStatement(bool* ok) {
1758 // ContinueStatement ::
1759 // 'continue' Identifier? ';'
1760
1761 int pos = peek_position();
1762 Expect(Token::CONTINUE, CHECK_OK);
1763 const AstRawString* label = NULL;
1764 Token::Value tok = peek();
1765 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
1766 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1767 // ECMA allows "eval" or "arguments" as labels even in strict mode.
1768 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
1769 }
1770 IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
1771 if (target == NULL) {
1772 // Illegal continue statement.
1773 MessageTemplate::Template message = MessageTemplate::kIllegalContinue;
1774 if (label != NULL) {
1775 message = MessageTemplate::kUnknownLabel;
1776 }
1777 ReportMessage(message, label);
1778 *ok = false;
1779 return NULL;
1780 }
1781 ExpectSemicolon(CHECK_OK);
1782 return factory()->NewContinueStatement(target, pos);
1783 }
1784
1785
1786 Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
1787 bool* ok) {
1788 // BreakStatement ::
1789 // 'break' Identifier? ';'
1790
1791 int pos = peek_position();
1792 Expect(Token::BREAK, CHECK_OK);
1793 const AstRawString* label = NULL;
1794 Token::Value tok = peek();
1795 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
1796 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1797 // ECMA allows "eval" or "arguments" as labels even in strict mode.
1798 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
1799 }
1800 // Parse labeled break statements that target themselves into
1801 // empty statements, e.g. 'l1: l2: l3: break l2;'
1802 if (label != NULL && ContainsLabel(labels, label)) {
1803 ExpectSemicolon(CHECK_OK);
1804 return factory()->NewEmptyStatement(pos);
1805 }
1806 BreakableStatement* target = NULL;
1807 target = LookupBreakTarget(label, CHECK_OK);
1808 if (target == NULL) {
1809 // Illegal break statement.
1810 MessageTemplate::Template message = MessageTemplate::kIllegalBreak;
1811 if (label != NULL) {
1812 message = MessageTemplate::kUnknownLabel;
1813 }
1814 ReportMessage(message, label);
1815 *ok = false;
1816 return NULL;
1817 }
1818 ExpectSemicolon(CHECK_OK);
1819 return factory()->NewBreakStatement(target, pos);
1820 }
1821
1822
1823 Statement* Parser::ParseReturnStatement(bool* ok) {
1824 // ReturnStatement ::
1825 // 'return' Expression? ';'
1826
1827 // Consume the return token. It is necessary to do that before
1828 // reporting any errors on it, because of the way errors are
1829 // reported (underlining).
1830 Expect(Token::RETURN, CHECK_OK);
1831 Scanner::Location loc = scanner()->location();
1832
1833 Token::Value tok = peek();
1834 Statement* result;
1835 Expression* return_value;
1836 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
1837 tok == Token::SEMICOLON ||
1838 tok == Token::RBRACE ||
1839 tok == Token::EOS) {
1840 if (IsSubclassConstructor(function_state_->kind())) {
1841 return_value = ThisExpression(loc.beg_pos);
1842 } else {
1843 return_value = GetLiteralUndefined(position());
1844 }
1845 } else {
1846 int pos = peek_position();
1847
1848 if (IsSubclassConstructor(function_state_->kind())) {
1849 // Because of the return code rewriting that happens in case of a subclass
1850 // constructor we don't want to accept tail calls, therefore we don't set
1851 // ReturnExprScope to kInsideValidReturnStatement here.
1852 return_value = ParseExpression(true, CHECK_OK);
1853
1854 // For subclass constructors we need to return this in case of undefined
1855 // return a Smi (transformed into an exception in the ConstructStub)
1856 // for a non object.
1857 //
1858 // return expr;
1859 //
1860 // Is rewritten as:
1861 //
1862 // return (temp = expr) === undefined ? this :
1863 // %_IsJSReceiver(temp) ? temp : 1;
1864
1865 // temp = expr
1866 Variable* temp = NewTemporary(ast_value_factory()->empty_string());
1867 Assignment* assign = factory()->NewAssignment(
1868 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
1869
1870 // %_IsJSReceiver(temp)
1871 ZoneList<Expression*>* is_spec_object_args =
1872 new (zone()) ZoneList<Expression*>(1, zone());
1873 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
1874 Expression* is_spec_object_call = factory()->NewCallRuntime(
1875 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
1876
1877 // %_IsJSReceiver(temp) ? temp : 1;
1878 Expression* is_object_conditional = factory()->NewConditional(
1879 is_spec_object_call, factory()->NewVariableProxy(temp),
1880 factory()->NewSmiLiteral(1, pos), pos);
1881
1882 // temp === undefined
1883 Expression* is_undefined = factory()->NewCompareOperation(
1884 Token::EQ_STRICT, assign,
1885 factory()->NewUndefinedLiteral(kNoSourcePosition), pos);
1886
1887 // is_undefined ? this : is_object_conditional
1888 return_value = factory()->NewConditional(
1889 is_undefined, ThisExpression(pos), is_object_conditional, pos);
1890 } else {
1891 ReturnExprScope maybe_allow_tail_calls(
1892 function_state_, ReturnExprContext::kInsideValidReturnStatement);
1893 return_value = ParseExpression(true, CHECK_OK);
1894
1895 if (allow_tailcalls() && !is_sloppy(language_mode()) && !is_resumable()) {
1896 // ES6 14.6.1 Static Semantics: IsInTailPosition
1897 function_state_->AddImplicitTailCallExpression(return_value);
1898 }
1899 }
1900 }
1901 ExpectSemicolon(CHECK_OK);
1902
1903 if (is_generator()) {
1904 return_value = BuildIteratorResult(return_value, true);
1905 } else if (is_async_function()) {
1906 return_value = BuildResolvePromise(return_value, return_value->position());
1907 }
1908
1909 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
1910
1911 DeclarationScope* decl_scope = GetDeclarationScope();
1912 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
1913 ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
1914 *ok = false;
1915 return NULL;
1916 }
1917 return result;
1918 }
1919
1920
1921 Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
1922 bool* ok) {
1923 // WithStatement ::
1924 // 'with' '(' Expression ')' Statement
1925
1926 Expect(Token::WITH, CHECK_OK);
1927 int pos = position();
1928
1929 if (is_strict(language_mode())) {
1930 ReportMessage(MessageTemplate::kStrictWith);
1931 *ok = false;
1932 return NULL;
1933 }
1934
1935 Expect(Token::LPAREN, CHECK_OK);
1936 Expression* expr = ParseExpression(true, CHECK_OK);
1937 Expect(Token::RPAREN, CHECK_OK);
1938
1939 Scope* with_scope = NewScope(WITH_SCOPE);
1940 Statement* body;
1941 {
1942 BlockState block_state(&scope_state_, with_scope);
1943 with_scope->set_start_position(scanner()->peek_location().beg_pos);
1944 body = ParseScopedStatement(labels, true, CHECK_OK);
1945 with_scope->set_end_position(scanner()->location().end_pos);
1946 }
1947 return factory()->NewWithStatement(with_scope, expr, body, pos);
1948 }
1949
1950
1951 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { 1722 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1952 // CaseClause :: 1723 // CaseClause ::
1953 // 'case' Expression ':' StatementList 1724 // 'case' Expression ':' StatementList
1954 // 'default' ':' StatementList 1725 // 'default' ':' StatementList
1955 1726
1956 Expression* label = NULL; // NULL expression indicates default case 1727 Expression* label = NULL; // NULL expression indicates default case
1957 if (peek() == Token::CASE) { 1728 if (peek() == Token::CASE) {
1958 Expect(Token::CASE, CHECK_OK); 1729 Expect(Token::CASE, CHECK_OK);
1959 label = ParseExpression(true, CHECK_OK); 1730 label = ParseExpression(true, CHECK_OK);
1960 } else { 1731 } else {
(...skipping 4017 matching lines...) Expand 10 before | Expand all | Expand 10 after
5978 node->Print(Isolate::Current()); 5749 node->Print(Isolate::Current());
5979 } 5750 }
5980 #endif // DEBUG 5751 #endif // DEBUG
5981 5752
5982 #undef CHECK_OK 5753 #undef CHECK_OK
5983 #undef CHECK_OK_VOID 5754 #undef CHECK_OK_VOID
5984 #undef CHECK_FAILED 5755 #undef CHECK_FAILED
5985 5756
5986 } // namespace internal 5757 } // namespace internal
5987 } // namespace v8 5758 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698