From e79ff8275c9117e925c03c087c4b8e9760c24404 Mon Sep 17 00:00:00 2001 From: "marja@chromium.org" Date: Fri, 21 Mar 2014 10:34:51 +0000 Subject: [PATCH] Move new expression parsing funcs to ParserBase. Functions moved: ParseMemberWithNewPrefixesExpression, ParseMemberExpression, ParseMemberExpressionContinuation. Now all Parse*Expression functions are in ParserBase. R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/207633003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20153 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/parser.cc | 137 +++++---------------------------------------------- src/parser.h | 7 +-- src/preparser.cc | 110 ----------------------------------------- src/preparser.h | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 154 insertions(+), 247 deletions(-) diff --git a/src/parser.cc b/src/parser.cc index c0d3360..9724ec7 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -439,6 +439,17 @@ bool ParserTraits::IsIdentifier(Expression* expression) { } +void ParserTraits::PushPropertyName(FuncNameInferrer* fni, + Expression* expression) { + if (expression->IsPropertyName()) { + fni->PushLiteralName(expression->AsLiteral()->AsPropertyName()); + } else { + fni->PushLiteralName( + parser_->isolate()->factory()->anonymous_function_string()); + } +} + + void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, Expression* right) { ASSERT(left != NULL); @@ -750,11 +761,6 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral( } -Expression* ParserTraits::ParseMemberWithNewPrefixesExpression(bool* ok) { - return parser_->ParseMemberWithNewPrefixesExpression(ok); -} - - Parser::Parser(CompilationInfo* info) : ParserBase(&scanner_, info->isolate()->stack_guard()->real_climit(), @@ -3053,127 +3059,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { } -Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) { - // NewExpression :: - // ('new')+ MemberExpression - - // The grammar for new expressions is pretty warped. We can have several 'new' - // keywords following each other, and then a MemberExpression. When we see '(' - // after the MemberExpression, it's associated with the rightmost unassociated - // 'new' to create a NewExpression with arguments. However, a NewExpression - // can also occur without arguments. - - // Examples of new expression: - // new foo.bar().baz means (new (foo.bar)()).baz - // new foo()() means (new foo())() - // new new foo()() means (new (new foo())()) - // new new foo means new (new foo) - // new new foo() means new (new foo()) - // new new foo().bar().baz means (new (new foo()).bar()).baz - - if (peek() == Token::NEW) { - Consume(Token::NEW); - int new_pos = position(); - Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK); - if (peek() == Token::LPAREN) { - // NewExpression with arguments. - ZoneList* args = ParseArguments(CHECK_OK); - result = factory()->NewCallNew(result, args, new_pos); - // The expression can still continue with . or [ after the arguments. - result = ParseMemberExpressionContinuation(result, CHECK_OK); - return result; - } - // NewExpression without arguments. - return factory()->NewCallNew( - result, new(zone()) ZoneList(0, zone()), new_pos); - } - // No 'new' keyword. - return ParseMemberExpression(ok); -} - - -Expression* Parser::ParseMemberExpression(bool* ok) { - // MemberExpression :: - // (PrimaryExpression | FunctionLiteral) - // ('[' Expression ']' | '.' Identifier | Arguments)* - - // The '[' Expression ']' and '.' Identifier parts are parsed by - // ParseMemberExpressionContinuation, and the Arguments part is parsed by the - // caller. - - // Parse the initial primary or function expression. - Expression* result = NULL; - if (peek() == Token::FUNCTION) { - Consume(Token::FUNCTION); - int function_token_position = position(); - bool is_generator = allow_generators() && Check(Token::MUL); - Handle name; - bool is_strict_reserved_name = false; - Scanner::Location function_name_location = Scanner::Location::invalid(); - FunctionLiteral::FunctionType function_type = - FunctionLiteral::ANONYMOUS_EXPRESSION; - if (peek_any_identifier()) { - name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, - CHECK_OK); - function_name_location = scanner()->location(); - function_type = FunctionLiteral::NAMED_EXPRESSION; - } - result = ParseFunctionLiteral(name, - function_name_location, - is_strict_reserved_name, - is_generator, - function_token_position, - function_type, - CHECK_OK); - } else { - result = ParsePrimaryExpression(CHECK_OK); - } - - result = ParseMemberExpressionContinuation(result, CHECK_OK); - return result; -} - - -Expression* Parser::ParseMemberExpressionContinuation(Expression* expression, - bool* ok) { - // Parses this part of MemberExpression: - // ('[' Expression ']' | '.' Identifier)* - while (true) { - switch (peek()) { - case Token::LBRACK: { - Consume(Token::LBRACK); - int pos = position(); - Expression* index = ParseExpression(true, CHECK_OK); - expression = factory()->NewProperty(expression, index, pos); - if (fni_ != NULL) { - if (index->IsPropertyName()) { - fni_->PushLiteralName(index->AsLiteral()->AsPropertyName()); - } else { - fni_->PushLiteralName( - isolate()->factory()->anonymous_function_string()); - } - } - Expect(Token::RBRACK, CHECK_OK); - break; - } - case Token::PERIOD: { - Consume(Token::PERIOD); - int pos = position(); - Handle name = ParseIdentifierName(CHECK_OK); - expression = factory()->NewProperty( - expression, factory()->NewLiteral(name, pos), pos); - if (fni_ != NULL) fni_->PushLiteralName(name); - break; - } - default: - return expression; - } - } - ASSERT(false); - return NULL; -} - - DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser // contexts this is used as a statement which invokes the debugger as i a diff --git a/src/parser.h b/src/parser.h index 4febdc8..f496267 100644 --- a/src/parser.h +++ b/src/parser.h @@ -475,6 +475,7 @@ class ParserTraits { static void PushLiteralName(FuncNameInferrer* fni, Handle id) { fni->PushLiteralName(id); } + void PushPropertyName(FuncNameInferrer* fni, Expression* expression); static void CheckFunctionLiteralInsideTopLevelObjectLiteral( Scope* scope, Expression* value, bool* has_function) { @@ -549,6 +550,7 @@ class ParserTraits { static Literal* EmptyLiteral() { return NULL; } + // Used in error return values. static ZoneList* NullExpressionList() { return NULL; } @@ -589,7 +591,6 @@ class ParserTraits { int function_token_position, FunctionLiteral::FunctionType type, bool* ok); - Expression* ParseMemberWithNewPrefixesExpression(bool* ok); private: Parser* parser_; @@ -725,10 +726,6 @@ class Parser : public ParserBase { // Support for hamony block scoped bindings. Block* ParseScopedBlock(ZoneStringList* labels, bool* ok); - Expression* ParseMemberWithNewPrefixesExpression(bool* ok); - Expression* ParseMemberExpression(bool* ok); - Expression* ParseMemberExpressionContinuation(Expression* expression, - bool* ok); // Initialize the components of a for-in / for-of statement. void InitializeForEachStatement(ForEachStatement* stmt, Expression* each, diff --git a/src/preparser.cc b/src/preparser.cc index 9473701..459cb6a 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -146,12 +146,6 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral( } -PreParserExpression PreParserTraits::ParseMemberWithNewPrefixesExpression( - bool* ok) { - return pre_parser_->ParseMemberWithNewPrefixesExpression(ok); -} - - PreParser::PreParseResult PreParser::PreParseLazyFunction( StrictMode strict_mode, bool is_generator, ParserRecorder* log) { log_ = log; @@ -843,110 +837,6 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { #undef DUMMY -PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( - bool* ok) { - // NewExpression :: - // ('new')+ MemberExpression - - // See Parser::ParseNewExpression. - - if (peek() == Token::NEW) { - Consume(Token::NEW); - ParseMemberWithNewPrefixesExpression(CHECK_OK); - Expression expression = Expression::Default(); - if (peek() == Token::LPAREN) { - // NewExpression with arguments. - ParseArguments(CHECK_OK); - // The expression can still continue with . or [ after the arguments. Here - // we need to transmit the "is valid left hand side" property of the - // expression. - expression = - ParseMemberExpressionContinuation(Expression::Default(), CHECK_OK); - } - return expression; - } - // No 'new' keyword. - return ParseMemberExpression(ok); -} - - -PreParser::Expression PreParser::ParseMemberExpression(bool* ok) { - // MemberExpression :: - // (PrimaryExpression | FunctionLiteral) - // ('[' Expression ']' | '.' Identifier | Arguments)* - - // The '[' Expression ']' and '.' Identifier parts are parsed by - // ParseMemberExpressionContinuation, and the Arguments part is parsed by the - // caller. - - // Parse the initial primary or function expression. - Expression result = Expression::Default(); - if (peek() == Token::FUNCTION) { - Consume(Token::FUNCTION); - int function_token_position = position(); - bool is_generator = allow_generators() && Check(Token::MUL); - Identifier name = Identifier::Default(); - bool is_strict_reserved_name = false; - Scanner::Location function_name_location = Scanner::Location::invalid(); - FunctionLiteral::FunctionType function_type = - FunctionLiteral::ANONYMOUS_EXPRESSION; - if (peek_any_identifier()) { - name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, - CHECK_OK); - function_name_location = scanner()->location(); - function_type = FunctionLiteral::NAMED_EXPRESSION; - } - result = ParseFunctionLiteral(name, - function_name_location, - is_strict_reserved_name, - is_generator, - function_token_position, - function_type, - CHECK_OK); - } else { - result = ParsePrimaryExpression(CHECK_OK); - } - result = ParseMemberExpressionContinuation(result, CHECK_OK); - return result; -} - - -PreParser::Expression PreParser::ParseMemberExpressionContinuation( - PreParserExpression expression, bool* ok) { - // Parses this part of MemberExpression: - // ('[' Expression ']' | '.' Identifier)* - while (true) { - switch (peek()) { - case Token::LBRACK: { - Consume(Token::LBRACK); - ParseExpression(true, CHECK_OK); - Expect(Token::RBRACK, CHECK_OK); - if (expression.IsThis()) { - expression = Expression::ThisProperty(); - } else { - expression = Expression::Property(); - } - break; - } - case Token::PERIOD: { - Consume(Token::PERIOD); - ParseIdentifierName(CHECK_OK); - if (expression.IsThis()) { - expression = Expression::ThisProperty(); - } else { - expression = Expression::Property(); - } - break; - } - default: - return expression; - } - } - ASSERT(false); - return PreParserExpression::Default(); -} - - PreParser::Expression PreParser::ParseFunctionLiteral( Identifier function_name, Scanner::Location function_name_location, diff --git a/src/preparser.h b/src/preparser.h index 7977fe2..ee8e46b 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -420,6 +420,10 @@ class ParserBase : public Traits { ExpressionT ParseUnaryExpression(bool* ok); ExpressionT ParsePostfixExpression(bool* ok); ExpressionT ParseLeftHandSideExpression(bool* ok); + ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); + ExpressionT ParseMemberExpression(bool* ok); + ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, + bool* ok); // Used to detect duplicates in object literals. Each of the values // kGetterProperty, kSetterProperty and kValueProperty represents @@ -504,6 +508,7 @@ class ParserBase : public Traits { class PreParserIdentifier { public: + PreParserIdentifier() : type_(kUnknownIdentifier) {} static PreParserIdentifier Default() { return PreParserIdentifier(kUnknownIdentifier); } @@ -791,6 +796,11 @@ class PreParserFactory { int pos) { return PreParserExpression::Default(); } + PreParserExpression NewCallNew(PreParserExpression expression, + PreParserExpressionList arguments, + int pos) { + return PreParserExpression::Default(); + } }; @@ -860,7 +870,12 @@ class PreParserTraits { // operations interleaved with the recursive descent. static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) { // PreParser should not use FuncNameInferrer. - ASSERT(false); + UNREACHABLE(); + } + static void PushPropertyName(FuncNameInferrer* fni, + PreParserExpression expression) { + // PreParser should not use FuncNameInferrer. + UNREACHABLE(); } static void CheckFunctionLiteralInsideTopLevelObjectLiteral( @@ -979,7 +994,6 @@ class PreParserTraits { int function_token_position, FunctionLiteral::FunctionType type, bool* ok); - PreParserExpression ParseMemberWithNewPrefixesExpression(bool* ok); private: PreParser* pre_parser_; @@ -1143,10 +1157,6 @@ class PreParser : public ParserBase { Statement ParseTryStatement(bool* ok); Statement ParseDebuggerStatement(bool* ok); Expression ParseConditionalExpression(bool accept_IN, bool* ok); - Expression ParseMemberExpression(bool* ok); - Expression ParseMemberExpressionContinuation(PreParserExpression expression, - bool* ok); - Expression ParseMemberWithNewPrefixesExpression(bool* ok); Expression ParseObjectLiteral(bool* ok); Expression ParseV8Intrinsic(bool* ok); @@ -1994,6 +2004,131 @@ ParserBase::ParseLeftHandSideExpression(bool* ok) { } +template +typename ParserBase::ExpressionT +ParserBase::ParseMemberWithNewPrefixesExpression(bool* ok) { + // NewExpression :: + // ('new')+ MemberExpression + + // The grammar for new expressions is pretty warped. We can have several 'new' + // keywords following each other, and then a MemberExpression. When we see '(' + // after the MemberExpression, it's associated with the rightmost unassociated + // 'new' to create a NewExpression with arguments. However, a NewExpression + // can also occur without arguments. + + // Examples of new expression: + // new foo.bar().baz means (new (foo.bar)()).baz + // new foo()() means (new foo())() + // new new foo()() means (new (new foo())()) + // new new foo means new (new foo) + // new new foo() means new (new foo()) + // new new foo().bar().baz means (new (new foo()).bar()).baz + + if (peek() == Token::NEW) { + Consume(Token::NEW); + int new_pos = position(); + ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); + if (peek() == Token::LPAREN) { + // NewExpression with arguments. + typename Traits::Type::ExpressionList args = + this->ParseArguments(CHECK_OK); + result = factory()->NewCallNew(result, args, new_pos); + // The expression can still continue with . or [ after the arguments. + result = this->ParseMemberExpressionContinuation(result, CHECK_OK); + return result; + } + // NewExpression without arguments. + return factory()->NewCallNew(result, this->NewExpressionList(0, zone_), + new_pos); + } + // No 'new' keyword. + return this->ParseMemberExpression(ok); +} + + +template +typename ParserBase::ExpressionT +ParserBase::ParseMemberExpression(bool* ok) { + // MemberExpression :: + // (PrimaryExpression | FunctionLiteral) + // ('[' Expression ']' | '.' Identifier | Arguments)* + + // The '[' Expression ']' and '.' Identifier parts are parsed by + // ParseMemberExpressionContinuation, and the Arguments part is parsed by the + // caller. + + // Parse the initial primary or function expression. + ExpressionT result = this->EmptyExpression(); + if (peek() == Token::FUNCTION) { + Consume(Token::FUNCTION); + int function_token_position = position(); + bool is_generator = allow_generators() && Check(Token::MUL); + IdentifierT name; + bool is_strict_reserved_name = false; + Scanner::Location function_name_location = Scanner::Location::invalid(); + FunctionLiteral::FunctionType function_type = + FunctionLiteral::ANONYMOUS_EXPRESSION; + if (peek_any_identifier()) { + name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, + CHECK_OK); + function_name_location = scanner()->location(); + function_type = FunctionLiteral::NAMED_EXPRESSION; + } + result = this->ParseFunctionLiteral(name, + function_name_location, + is_strict_reserved_name, + is_generator, + function_token_position, + function_type, + CHECK_OK); + } else { + result = ParsePrimaryExpression(CHECK_OK); + } + + result = ParseMemberExpressionContinuation(result, CHECK_OK); + return result; +} + + +template +typename ParserBase::ExpressionT +ParserBase::ParseMemberExpressionContinuation(ExpressionT expression, + bool* ok) { + // Parses this part of MemberExpression: + // ('[' Expression ']' | '.' Identifier)* + while (true) { + switch (peek()) { + case Token::LBRACK: { + Consume(Token::LBRACK); + int pos = position(); + ExpressionT index = this->ParseExpression(true, CHECK_OK); + expression = factory()->NewProperty(expression, index, pos); + if (fni_ != NULL) { + this->PushPropertyName(fni_, index); + } + Expect(Token::RBRACK, CHECK_OK); + break; + } + case Token::PERIOD: { + Consume(Token::PERIOD); + int pos = position(); + IdentifierT name = ParseIdentifierName(CHECK_OK); + expression = factory()->NewProperty( + expression, factory()->NewLiteral(name, pos), pos); + if (fni_ != NULL) { + this->PushLiteralName(fni_, name); + } + break; + } + default: + return expression; + } + } + ASSERT(false); + return this->EmptyExpression(); +} + + #undef CHECK_OK #undef CHECK_OK_CUSTOM -- 2.7.4