From f3ee83b63142aad78a71ebd83b3abc463ea60612 Mon Sep 17 00:00:00 2001 From: dslomov Date: Wed, 22 Apr 2015 05:35:05 -0700 Subject: [PATCH] Introduce "expression classifier" to the parser. R=marja@chromium.org,rossberg@chromium.org Review URL: https://codereview.chromium.org/1065983005 Cr-Commit-Position: refs/heads/master@{#28005} --- src/bootstrapper.cc | 37 +++--- src/flag-definitions.h | 3 +- src/parser.cc | 35 ++++-- src/preparser.cc | 29 +++-- src/preparser.h | 305 ++++++++++++++++++++++++++++++++----------------- src/scanner.h | 8 ++ 6 files changed, 281 insertions(+), 136 deletions(-) diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index cb9bdfa..1a5bfcf 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -1672,6 +1672,7 @@ EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_computed_property_names) EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_rest_parameters) EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_reflect) EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_spreadcalls) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_destructuring) void Genesis::InstallNativeFunctions_harmony_proxies() { @@ -1700,6 +1701,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_unicode) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_computed_property_names) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_rest_parameters) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spreadcalls) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_destructuring) void Genesis::InitializeGlobal_harmony_regexps() { Handle builtins(native_context()->builtins()); @@ -2304,27 +2306,28 @@ bool Genesis::InstallNatives() { bool Genesis::InstallExperimentalNatives() { static const char* harmony_arrays_natives[] = { - "native harmony-array.js", "native harmony-typedarray.js", NULL}; + "native harmony-array.js", "native harmony-typedarray.js", nullptr}; static const char* harmony_array_includes_natives[] = { - "native harmony-array-includes.js", NULL}; - static const char* harmony_proxies_natives[] = {"native proxy.js", NULL}; - static const char* harmony_classes_natives[] = {NULL}; - static const char* harmony_modules_natives[] = {NULL}; - static const char* harmony_object_literals_natives[] = {NULL}; - static const char* harmony_regexps_natives[] = { - "native harmony-regexp.js", NULL}; - static const char* harmony_arrow_functions_natives[] = {NULL}; + "native harmony-array-includes.js", nullptr}; + static const char* harmony_proxies_natives[] = {"native proxy.js", nullptr}; + static const char* harmony_classes_natives[] = {nullptr}; + static const char* harmony_modules_natives[] = {nullptr}; + static const char* harmony_object_literals_natives[] = {nullptr}; + static const char* harmony_regexps_natives[] = {"native harmony-regexp.js", + nullptr}; + static const char* harmony_arrow_functions_natives[] = {nullptr}; static const char* harmony_tostring_natives[] = {"native harmony-tostring.js", - NULL}; - static const char* harmony_sloppy_natives[] = {NULL}; - static const char* harmony_unicode_natives[] = {NULL}; - static const char* harmony_unicode_regexps_natives[] = {NULL}; - static const char* harmony_computed_property_names_natives[] = {NULL}; - static const char* harmony_rest_parameters_natives[] = {NULL}; + nullptr}; + static const char* harmony_sloppy_natives[] = {nullptr}; + static const char* harmony_unicode_natives[] = {nullptr}; + static const char* harmony_unicode_regexps_natives[] = {nullptr}; + static const char* harmony_computed_property_names_natives[] = {nullptr}; + static const char* harmony_rest_parameters_natives[] = {nullptr}; static const char* harmony_reflect_natives[] = {"native harmony-reflect.js", - NULL}; + nullptr}; static const char* harmony_spreadcalls_natives[] = { - "native harmony-spread.js", NULL}; + "native harmony-spread.js", nullptr}; + static const char* harmony_destructuring_natives[] = {nullptr}; for (int i = ExperimentalNatives::GetDebuggerCount(); i < ExperimentalNatives::GetBuiltinsCount(); i++) { diff --git a/src/flag-definitions.h b/src/flag-definitions.h index c749ec0..493f3b0 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -191,7 +191,8 @@ DEFINE_IMPLICATION(es_staging, harmony) V(harmony_proxies, "harmony proxies") \ V(harmony_sloppy, "harmony features in sloppy mode") \ V(harmony_unicode_regexps, "harmony unicode regexps") \ - V(harmony_reflect, "harmony Reflect API") + V(harmony_reflect, "harmony Reflect API") \ + V(harmony_destructuring, "harmony destructuring") // Features that are complete (but still behind --harmony/es-staging flag). #define HARMONY_STAGED(V) \ diff --git a/src/parser.cc b/src/parser.cc index 2961a1a..b9ae09a 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -1146,8 +1146,10 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, } if (ok) { - Expression* expression = - ParseArrowFunctionLiteral(scope, error_locs, has_rest, &ok); + ExpressionClassifier classifier; + Expression* expression = ParseArrowFunctionLiteral( + scope, error_locs, has_rest, &classifier, &ok); + // TODO(dslomov): report error if not a valid expression. if (ok) { // Scanning must end at the same position that was recorded // previously. If not, parsing has been interrupted due to a stack @@ -1614,7 +1616,10 @@ Statement* Parser::ParseExportDefault(bool* ok) { default: { int pos = peek_position(); - Expression* expr = ParseAssignmentExpression(true, CHECK_OK); + ExpressionClassifier classifier; + Expression* expr = ParseAssignmentExpression(true, &classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. + ExpectSemicolon(CHECK_OK); result = factory()->NewExpressionStatement(expr, pos); break; @@ -2428,7 +2433,10 @@ Block* Parser::ParseVariableDeclarations( (mode == CONST && !is_for_iteration_variable)) { Expect(Token::ASSIGN, CHECK_OK); pos = position(); - value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); + ExpressionClassifier classifier; + value = ParseAssignmentExpression(var_context != kForStatement, + &classifier, CHECK_OK); + // TODO(dslomov): check that expression is valid. variable_loc.end_pos = scanner()->location().end_pos; if (first_initializer_loc && !first_initializer_loc->IsValid()) { @@ -2613,11 +2621,13 @@ Statement* Parser::ParseExpressionOrLabelledStatement( i::IsConstructor(function_state_->kind())) { bool is_this = peek() == Token::THIS; Expression* expr; + ExpressionClassifier classifier; if (is_this) { - expr = ParseStrongInitializationExpression(CHECK_OK); + expr = ParseStrongInitializationExpression(&classifier, CHECK_OK); } else { - expr = ParseStrongSuperCallExpression(CHECK_OK); + expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK); } + // TODO(dslomov): report error if not a valid expression. switch (peek()) { case Token::SEMICOLON: Consume(Token::SEMICOLON); @@ -4338,7 +4348,9 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, Expression* extends = NULL; if (Check(Token::EXTENDS)) { block_scope->set_start_position(scanner()->location().end_pos); - extends = ParseLeftHandSideExpression(CHECK_OK); + ExpressionClassifier classifier; + extends = ParseLeftHandSideExpression(&classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. } else { block_scope->set_start_position(scanner()->location().end_pos); } @@ -4359,9 +4371,11 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, const bool is_static = false; bool is_computed_name = false; // Classes do not care about computed // property names here. + ExpressionClassifier classifier; ObjectLiteral::Property* property = ParsePropertyDefinition( &checker, in_class, has_extends, is_static, &is_computed_name, - &has_seen_constructor, CHECK_OK); + &has_seen_constructor, &classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. if (has_seen_constructor && constructor == NULL) { constructor = GetPropertyValue(property)->AsFunctionLiteral(); @@ -4410,7 +4424,10 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); Scanner::Location spread_pos; - ZoneList* args = ParseArguments(&spread_pos, CHECK_OK); + ExpressionClassifier classifier; + ZoneList* args = + ParseArguments(&spread_pos, &classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. DCHECK(!spread_pos.IsValid()); diff --git a/src/preparser.cc b/src/preparser.cc index caa383a..950f7b5 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -520,7 +520,10 @@ PreParser::Statement PreParser::ParseVariableDeclarations( // require initializers for multiple consts. (is_strict_const && peek() == Token::COMMA)) { Expect(Token::ASSIGN, CHECK_OK); - ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); + ExpressionClassifier classifier; + ParseAssignmentExpression(var_context != kForStatement, &classifier, + CHECK_OK); + // TODO(dslomov): report error if not valid expression. variable_loc.end_pos = scanner()->location().end_pos; if (first_initializer_loc && !first_initializer_loc->IsValid()) { @@ -559,11 +562,13 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { i::IsConstructor(function_state_->kind())) { bool is_this = peek() == Token::THIS; Expression expr = Expression::Default(); + ExpressionClassifier classifier; if (is_this) { - expr = ParseStrongInitializationExpression(CHECK_OK); + expr = ParseStrongInitializationExpression(&classifier, CHECK_OK); } else { - expr = ParseStrongSuperCallExpression(CHECK_OK); + expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK); } + // TODO(dslomov): report error if not a valid expression. switch (peek()) { case Token::SEMICOLON: Consume(Token::SEMICOLON); @@ -592,7 +597,10 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { } bool starts_with_identifier = peek_any_identifier(); - Expression expr = ParseExpression(true, CHECK_OK); + ExpressionClassifier classifier; + Expression expr = ParseExpression(true, &classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. + // Even if the expression starts with an identifier, it is not necessarily an // identifier. For example, "foo + bar" starts with an identifier but is not // an identifier. @@ -1081,7 +1089,9 @@ PreParserExpression PreParser::ParseClassLiteral( bool has_extends = Check(Token::EXTENDS); if (has_extends) { - ParseLeftHandSideExpression(CHECK_OK); + ExpressionClassifier classifier; + ParseLeftHandSideExpression(&classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. } ClassLiteralChecker checker(this); @@ -1094,8 +1104,11 @@ PreParserExpression PreParser::ParseClassLiteral( const bool is_static = false; bool is_computed_name = false; // Classes do not care about computed // property names here. + ExpressionClassifier classifier; ParsePropertyDefinition(&checker, in_class, has_extends, is_static, - &is_computed_name, &has_seen_constructor, CHECK_OK); + &is_computed_name, &has_seen_constructor, + &classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. } Expect(Token::RBRACE, CHECK_OK); @@ -1115,7 +1128,9 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { // Allow "eval" or "arguments" for backward compatibility. ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); Scanner::Location spread_pos; - ParseArguments(&spread_pos, ok); + ExpressionClassifier classifier; + ParseArguments(&spread_pos, &classifier, ok); + // TODO(dslomov): report error if not a valid expression. DCHECK(!spread_pos.IsValid()); diff --git a/src/preparser.h b/src/preparser.h index 0d71d93..3632051 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -600,40 +600,98 @@ class ParserBase : public Traits { bool* is_set, bool* ok); - ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok); - ExpressionT ParsePrimaryExpression(bool* ok); + class ExpressionClassifier { + public: + ExpressionClassifier() + : expression_error_(Scanner::Location::invalid()), + binding_pattern_error_(Scanner::Location::invalid()), + assignment_pattern_error_(Scanner::Location::invalid()) {} + + bool is_valid_expression() const { + return expression_error_ == Scanner::Location::invalid(); + } + + bool is_valid_binding_pattern() const { + return binding_pattern_error_ == Scanner::Location::invalid(); + } + + bool is_valid_assignmnent_pattern() const { + return assignment_pattern_error_ == Scanner::Location::invalid(); + } + + void RecordExpressionError(const Scanner::Location& loc) { + if (!is_valid_expression()) return; + expression_error_ = loc; + } + + void RecordBindingPatternError(const Scanner::Location& loc) { + if (!is_valid_binding_pattern()) return; + binding_pattern_error_ = loc; + } + + void RecordAssignmentPatternError(const Scanner::Location& loc) { + if (!is_valid_assignmnent_pattern()) return; + assignment_pattern_error_ = loc; + } + + private: + Scanner::Location expression_error_; + Scanner::Location binding_pattern_error_; + Scanner::Location assignment_pattern_error_; + }; + + ExpressionT ParseRegExpLiteral(bool seen_equal, + ExpressionClassifier* classifier, bool* ok); + + ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, + bool* ok); ExpressionT ParseExpression(bool accept_IN, bool* ok); - ExpressionT ParseArrayLiteral(bool* ok); + ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, + bool* ok); + ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, bool* is_static, bool* is_computed_name, - bool* ok); - ExpressionT ParseObjectLiteral(bool* ok); + ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); ObjectLiteralPropertyT ParsePropertyDefinition( ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, bool is_static, bool* is_computed_name, bool* has_seen_constructor, - bool* ok); + ExpressionClassifier* classifier, bool* ok); typename Traits::Type::ExpressionList ParseArguments( - Scanner::Location* first_spread_pos, bool* ok); - ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); - ExpressionT ParseYieldExpression(bool* ok); - ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); - ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); - 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); + Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, + bool* ok); + ExpressionT ParseAssignmentExpression(bool accept_IN, + ExpressionClassifier* classifier, + bool* ok); + ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseConditionalExpression(bool accept_IN, + ExpressionClassifier* classifier, + bool* ok); + ExpressionT ParseBinaryExpression(int prec, bool accept_IN, + ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok); + ExpressionT ParsePostfixExpression(ExpressionClassifier* classifier, + bool* ok); + ExpressionT ParseLeftHandSideExpression(ExpressionClassifier* classifier, + bool* ok); + ExpressionT ParseMemberWithNewPrefixesExpression( + ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseMemberExpressionContinuation( + ExpressionT expression, ExpressionClassifier* classifier, bool* ok); ExpressionT ParseArrowFunctionLiteral( Scope* function_scope, const FormalParameterErrorLocations& error_locs, - bool has_rest, bool* ok); - ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); + bool has_rest, ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, + ExpressionClassifier* classifier, bool* ok); void AddTemplateExpression(ExpressionT); - ExpressionT ParseSuperExpression(bool is_new, bool* ok); - ExpressionT ParseStrongInitializationExpression(bool* ok); - ExpressionT ParseStrongSuperCallExpression(bool* ok); + ExpressionT ParseSuperExpression(bool is_new, + ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseStrongInitializationExpression( + ExpressionClassifier* classifier, bool* ok); + ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier, + bool* ok); void ParseFormalParameter(FormalParameterScopeT* scope, FormalParameterErrorLocations* locs, bool is_rest, @@ -1989,7 +2047,7 @@ ParserBase::ParseIdentifierNameOrGetOrSet(bool* is_get, template typename ParserBase::ExpressionT ParserBase::ParseRegExpLiteral( - bool seen_equal, bool* ok) { + bool seen_equal, ExpressionClassifier* classifier, bool* ok) { int pos = peek_position(); if (!scanner()->ScanRegExpPattern(seen_equal)) { Next(); @@ -2026,9 +2084,11 @@ typename ParserBase::ExpressionT ParserBase::ParseRegExpLiteral( #define DUMMY ) // to make indentation work #undef DUMMY + template typename ParserBase::ExpressionT -ParserBase::ParsePrimaryExpression(bool* ok) { +ParserBase::ParsePrimaryExpression(ExpressionClassifier* classifier, + bool* ok) { // PrimaryExpression :: // 'this' // 'null' @@ -2094,19 +2154,19 @@ ParserBase::ParsePrimaryExpression(bool* ok) { } case Token::ASSIGN_DIV: - result = this->ParseRegExpLiteral(true, CHECK_OK); + result = this->ParseRegExpLiteral(true, classifier, CHECK_OK); break; case Token::DIV: - result = this->ParseRegExpLiteral(false, CHECK_OK); + result = this->ParseRegExpLiteral(false, classifier, CHECK_OK); break; case Token::LBRACK: - result = this->ParseArrayLiteral(CHECK_OK); + result = this->ParseArrayLiteral(classifier, CHECK_OK); break; case Token::LBRACE: - result = this->ParseObjectLiteral(CHECK_OK); + result = this->ParseObjectLiteral(classifier, CHECK_OK); break; case Token::LPAREN: @@ -2118,12 +2178,12 @@ ParserBase::ParsePrimaryExpression(bool* ok) { FormalParameterErrorLocations error_locs; bool has_rest = false; result = this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, - CHECK_OK); + classifier, CHECK_OK); } else { // Heuristically try to detect immediately called functions before // seeing the call parentheses. parenthesized_function_ = (peek() == Token::FUNCTION); - result = this->ParseExpression(true, CHECK_OK); + result = this->ParseExpression(true, classifier, CHECK_OK); result->increase_parenthesization_level(); Expect(Token::RPAREN, CHECK_OK); } @@ -2154,7 +2214,7 @@ ParserBase::ParsePrimaryExpression(bool* ok) { case Token::TEMPLATE_SPAN: case Token::TEMPLATE_TAIL: result = this->ParseTemplateLiteral(Traits::NoTemplateTag(), beg_pos, - CHECK_OK); + classifier, CHECK_OK); break; case Token::MOD: @@ -2175,19 +2235,32 @@ ParserBase::ParsePrimaryExpression(bool* ok) { return result; } -// Precedence = 1 + template typename ParserBase::ExpressionT ParserBase::ParseExpression( bool accept_IN, bool* ok) { + ExpressionClassifier classifier; + ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); + // TODO(dslomov): report error if not a valid expression. + return result; +} + + +// Precedence = 1 +template +typename ParserBase::ExpressionT ParserBase::ParseExpression( + bool accept_IN, ExpressionClassifier* classifier, bool* ok) { // Expression :: // AssignmentExpression // Expression ',' AssignmentExpression - ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK); + ExpressionT result = + this->ParseAssignmentExpression(accept_IN, classifier, CHECK_OK); while (peek() == Token::COMMA) { Expect(Token::COMMA, CHECK_OK); int pos = position(); - ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK); + ExpressionT right = + this->ParseAssignmentExpression(accept_IN, classifier, CHECK_OK); result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); } return result; @@ -2196,7 +2269,7 @@ typename ParserBase::ExpressionT ParserBase::ParseExpression( template typename ParserBase::ExpressionT ParserBase::ParseArrayLiteral( - bool* ok) { + ExpressionClassifier* classifier, bool* ok) { // ArrayLiteral :: // '[' Expression? (',' Expression?)* ']' @@ -2214,7 +2287,7 @@ typename ParserBase::ExpressionT ParserBase::ParseArrayLiteral( } elem = this->GetLiteralTheHole(peek_position(), factory()); } else { - elem = this->ParseAssignmentExpression(true, CHECK_OK); + elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK); } values->Add(elem, zone_); if (peek() != Token::RBRACK) { @@ -2233,7 +2306,7 @@ typename ParserBase::ExpressionT ParserBase::ParseArrayLiteral( template typename ParserBase::ExpressionT ParserBase::ParsePropertyName( IdentifierT* name, bool* is_get, bool* is_set, bool* is_static, - bool* is_computed_name, bool* ok) { + bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) { Token::Value token = peek(); int pos = peek_position(); @@ -2266,7 +2339,8 @@ typename ParserBase::ExpressionT ParserBase::ParsePropertyName( if (allow_harmony_computed_property_names_) { *is_computed_name = true; Consume(Token::LBRACK); - ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK); + ExpressionT expression = + ParseAssignmentExpression(true, classifier, CHECK_OK); Expect(Token::RBRACK, CHECK_OK); return expression; } @@ -2290,12 +2364,10 @@ typename ParserBase::ExpressionT ParserBase::ParsePropertyName( template typename ParserBase::ObjectLiteralPropertyT -ParserBase::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, - bool in_class, bool has_extends, - bool is_static, - bool* is_computed_name, - bool* has_seen_constructor, - bool* ok) { +ParserBase::ParsePropertyDefinition( + ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, + bool is_static, bool* is_computed_name, bool* has_seen_constructor, + ExpressionClassifier* classifier, bool* ok) { DCHECK(!in_class || is_static || has_seen_constructor != nullptr); ExpressionT value = this->EmptyExpression(); IdentifierT name = this->EmptyIdentifier(); @@ -2308,7 +2380,7 @@ ParserBase::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, int next_beg_pos = scanner()->peek_location().beg_pos; int next_end_pos = scanner()->peek_location().end_pos; ExpressionT name_expression = ParsePropertyName( - &name, &is_get, &is_set, &name_is_static, is_computed_name, + &name, &is_get, &is_set, &name_is_static, is_computed_name, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); if (fni_ != nullptr && !*is_computed_name) { @@ -2324,7 +2396,7 @@ ParserBase::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, } Consume(Token::COLON); value = this->ParseAssignmentExpression( - true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); + true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); } else if (is_generator || (allow_harmony_object_literals_ && peek() == Token::LPAREN)) { @@ -2360,7 +2432,7 @@ ParserBase::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, } else if (in_class && name_is_static && !is_static) { // static MethodDefinition return ParsePropertyDefinition(checker, true, has_extends, true, - is_computed_name, nullptr, ok); + is_computed_name, nullptr, classifier, ok); } else if (is_get || is_set) { // Accessor name = this->EmptyIdentifier(); @@ -2368,7 +2440,7 @@ ParserBase::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, name_token = peek(); name_expression = ParsePropertyName( - &name, &dont_care, &dont_care, &dont_care, is_computed_name, + &name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); if (!*is_computed_name) { @@ -2423,7 +2495,7 @@ ParserBase::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, template typename ParserBase::ExpressionT ParserBase::ParseObjectLiteral( - bool* ok) { + ExpressionClassifier* classifier, bool* ok) { // ObjectLiteral :: // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' @@ -2446,7 +2518,7 @@ typename ParserBase::ExpressionT ParserBase::ParseObjectLiteral( bool is_computed_name = false; ObjectLiteralPropertyT property = this->ParsePropertyDefinition( &checker, in_class, has_extends, is_static, &is_computed_name, NULL, - CHECK_OK); + classifier, CHECK_OK); if (is_computed_name) { has_computed_names = true; @@ -2489,7 +2561,8 @@ typename ParserBase::ExpressionT ParserBase::ParseObjectLiteral( template typename Traits::Type::ExpressionList ParserBase::ParseArguments( - Scanner::Location* first_spread_arg_loc, bool* ok) { + Scanner::Location* first_spread_arg_loc, ExpressionClassifier* classifier, + bool* ok) { // Arguments :: // '(' (AssignmentExpression)*[','] ')' @@ -2506,7 +2579,7 @@ typename Traits::Type::ExpressionList ParserBase::ParseArguments( if (is_spread) Consume(Token::ELLIPSIS); ExpressionT argument = this->ParseAssignmentExpression( - true, CHECK_OK_CUSTOM(NullExpressionList)); + true, classifier, CHECK_OK_CUSTOM(NullExpressionList)); if (is_spread) { if (!spread_arg.IsValid()) { spread_arg.beg_pos = start_pos; @@ -2556,7 +2629,9 @@ typename Traits::Type::ExpressionList ParserBase::ParseArguments( // Precedence = 2 template typename ParserBase::ExpressionT -ParserBase::ParseAssignmentExpression(bool accept_IN, bool* ok) { +ParserBase::ParseAssignmentExpression(bool accept_IN, + ExpressionClassifier* classifier, + bool* ok) { // AssignmentExpression :: // ConditionalExpression // ArrowFunction @@ -2566,13 +2641,13 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, bool* ok) { Scanner::Location lhs_location = scanner()->peek_location(); if (peek() == Token::YIELD && is_generator()) { - return this->ParseYieldExpression(ok); + return this->ParseYieldExpression(classifier, ok); } if (fni_ != NULL) fni_->Enter(); ParserBase::Checkpoint checkpoint(this); ExpressionT expression = - this->ParseConditionalExpression(accept_IN, CHECK_OK); + this->ParseConditionalExpression(accept_IN, classifier, CHECK_OK); if (allow_harmony_arrow_functions() && peek() == Token::ARROW) { checkpoint.Restore(); @@ -2583,8 +2658,8 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, bool* ok) { scope->set_start_position(lhs_location.beg_pos); this->ParseArrowFunctionFormalParameters(scope, expression, loc, &error_locs, &has_rest, CHECK_OK); - expression = - this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, CHECK_OK); + expression = this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, + classifier, CHECK_OK); return expression; } @@ -2600,7 +2675,8 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, bool* ok) { Token::Value op = Next(); // Get assignment operator. int pos = position(); - ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK); + ExpressionT right = + this->ParseAssignmentExpression(accept_IN, classifier, CHECK_OK); // TODO(1231235): We try to estimate the set of properties set by // constructors. We define a new property whenever there is an @@ -2633,7 +2709,8 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseYieldExpression(bool* ok) { +ParserBase::ParseYieldExpression(ExpressionClassifier* classifier, + bool* ok) { // YieldExpression :: // 'yield' ([no line terminator] '*'? AssignmentExpression)? int pos = peek_position(); @@ -2661,7 +2738,7 @@ ParserBase::ParseYieldExpression(bool* ok) { DCHECK_EQ(Yield::kDelegating, kind); // Delegating yields require an RHS; fall through. default: - expression = ParseAssignmentExpression(false, CHECK_OK); + expression = ParseAssignmentExpression(false, classifier, CHECK_OK); break; } } @@ -2681,22 +2758,26 @@ ParserBase::ParseYieldExpression(bool* ok) { // Precedence = 3 template typename ParserBase::ExpressionT -ParserBase::ParseConditionalExpression(bool accept_IN, bool* ok) { +ParserBase::ParseConditionalExpression(bool accept_IN, + ExpressionClassifier* classifier, + bool* ok) { // ConditionalExpression :: // LogicalOrExpression // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression int pos = peek_position(); // We start using the binary expression parser for prec >= 4 only! - ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK); + ExpressionT expression = + this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK); if (peek() != Token::CONDITIONAL) return expression; Consume(Token::CONDITIONAL); // In parsing the first assignment expression in conditional // expressions we always accept the 'in' keyword; see ECMA-262, // section 11.12, page 58. - ExpressionT left = ParseAssignmentExpression(true, CHECK_OK); + ExpressionT left = ParseAssignmentExpression(true, classifier, CHECK_OK); Expect(Token::COLON, CHECK_OK); - ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK); + ExpressionT right = + ParseAssignmentExpression(accept_IN, classifier, CHECK_OK); return factory()->NewConditional(expression, left, right, pos); } @@ -2704,16 +2785,19 @@ ParserBase::ParseConditionalExpression(bool accept_IN, bool* ok) { // Precedence >= 4 template typename ParserBase::ExpressionT -ParserBase::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { +ParserBase::ParseBinaryExpression(int prec, bool accept_IN, + ExpressionClassifier* classifier, + bool* ok) { DCHECK(prec >= 4); - ExpressionT x = this->ParseUnaryExpression(CHECK_OK); + ExpressionT x = this->ParseUnaryExpression(classifier, CHECK_OK); for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { // prec1 >= 4 while (Precedence(peek(), accept_IN) == prec1) { Token::Value op = Next(); Scanner::Location op_location = scanner()->location(); int pos = position(); - ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); + ExpressionT y = + ParseBinaryExpression(prec1 + 1, accept_IN, classifier, CHECK_OK); if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos, factory())) { @@ -2754,7 +2838,8 @@ ParserBase::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseUnaryExpression(bool* ok) { +ParserBase::ParseUnaryExpression(ExpressionClassifier* classifier, + bool* ok) { // UnaryExpression :: // PostfixExpression // 'delete' UnaryExpression @@ -2771,7 +2856,7 @@ ParserBase::ParseUnaryExpression(bool* ok) { if (Token::IsUnaryOp(op)) { op = Next(); int pos = position(); - ExpressionT expression = ParseUnaryExpression(CHECK_OK); + ExpressionT expression = ParseUnaryExpression(classifier, CHECK_OK); if (op == Token::DELETE && is_strict(language_mode())) { if (is_strong(language_mode())) { @@ -2791,7 +2876,7 @@ ParserBase::ParseUnaryExpression(bool* ok) { } else if (Token::IsCountOp(op)) { op = Next(); Scanner::Location lhs_location = scanner()->peek_location(); - ExpressionT expression = this->ParseUnaryExpression(CHECK_OK); + ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK); expression = this->CheckAndRewriteReferenceExpression( expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK); this->MarkExpressionAsAssigned(expression); @@ -2802,19 +2887,21 @@ ParserBase::ParseUnaryExpression(bool* ok) { position()); } else { - return this->ParsePostfixExpression(ok); + return this->ParsePostfixExpression(classifier, ok); } } template typename ParserBase::ExpressionT -ParserBase::ParsePostfixExpression(bool* ok) { +ParserBase::ParsePostfixExpression(ExpressionClassifier* classifier, + bool* ok) { // PostfixExpression :: // LeftHandSideExpression ('++' | '--')? Scanner::Location lhs_location = scanner()->peek_location(); - ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK); + ExpressionT expression = + this->ParseLeftHandSideExpression(classifier, CHECK_OK); if (!scanner()->HasAnyLineTerminatorBeforeNext() && Token::IsCountOp(peek())) { expression = this->CheckAndRewriteReferenceExpression( @@ -2834,18 +2921,20 @@ ParserBase::ParsePostfixExpression(bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseLeftHandSideExpression(bool* ok) { +ParserBase::ParseLeftHandSideExpression( + ExpressionClassifier* classifier, bool* ok) { // LeftHandSideExpression :: // (NewExpression | MemberExpression) ... - ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); + ExpressionT result = + this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); while (true) { switch (peek()) { case Token::LBRACK: { Consume(Token::LBRACK); int pos = position(); - ExpressionT index = ParseExpression(true, CHECK_OK); + ExpressionT index = ParseExpression(true, classifier, CHECK_OK); result = factory()->NewProperty(result, index, pos); Expect(Token::RBRACK, CHECK_OK); break; @@ -2879,7 +2968,7 @@ ParserBase::ParseLeftHandSideExpression(bool* ok) { } Scanner::Location spread_pos; typename Traits::Type::ExpressionList args = - ParseArguments(&spread_pos, CHECK_OK); + ParseArguments(&spread_pos, classifier, CHECK_OK); // Keep track of eval() calls since they disable all local variable // optimizations. @@ -2919,7 +3008,8 @@ ParserBase::ParseLeftHandSideExpression(bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseMemberWithNewPrefixesExpression(bool* ok) { +ParserBase::ParseMemberWithNewPrefixesExpression( + ExpressionClassifier* classifier, bool* ok) { // NewExpression :: // ('new')+ MemberExpression @@ -2943,15 +3033,15 @@ ParserBase::ParseMemberWithNewPrefixesExpression(bool* ok) { ExpressionT result = this->EmptyExpression(); if (peek() == Token::SUPER) { const bool is_new = true; - result = ParseSuperExpression(is_new, CHECK_OK); + result = ParseSuperExpression(is_new, classifier, CHECK_OK); } else { - result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); + result = this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); } if (peek() == Token::LPAREN) { // NewExpression with arguments. Scanner::Location spread_pos; typename Traits::Type::ExpressionList args = - this->ParseArguments(&spread_pos, CHECK_OK); + this->ParseArguments(&spread_pos, classifier, CHECK_OK); if (spread_pos.IsValid()) { args = Traits::PrepareSpreadArguments(args); @@ -2960,7 +3050,8 @@ ParserBase::ParseMemberWithNewPrefixesExpression(bool* ok) { result = factory()->NewCallNew(result, args, new_pos); } // The expression can still continue with . or [ after the arguments. - result = this->ParseMemberExpressionContinuation(result, CHECK_OK); + result = + this->ParseMemberExpressionContinuation(result, classifier, CHECK_OK); return result; } // NewExpression without arguments. @@ -2968,13 +3059,14 @@ ParserBase::ParseMemberWithNewPrefixesExpression(bool* ok) { new_pos); } // No 'new' or 'super' keyword. - return this->ParseMemberExpression(ok); + return this->ParseMemberExpression(classifier, ok); } template typename ParserBase::ExpressionT -ParserBase::ParseMemberExpression(bool* ok) { +ParserBase::ParseMemberExpression(ExpressionClassifier* classifier, + bool* ok) { // MemberExpression :: // (PrimaryExpression | FunctionLiteral | ClassLiteral) // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)* @@ -3008,19 +3100,20 @@ ParserBase::ParseMemberExpression(bool* ok) { CHECK_OK); } else if (peek() == Token::SUPER) { const bool is_new = false; - result = ParseSuperExpression(is_new, CHECK_OK); + result = ParseSuperExpression(is_new, classifier, CHECK_OK); } else { - result = ParsePrimaryExpression(CHECK_OK); + result = ParsePrimaryExpression(classifier, CHECK_OK); } - result = ParseMemberExpressionContinuation(result, CHECK_OK); + result = ParseMemberExpressionContinuation(result, classifier, CHECK_OK); return result; } template typename ParserBase::ExpressionT -ParserBase::ParseStrongInitializationExpression(bool* ok) { +ParserBase::ParseStrongInitializationExpression( + ExpressionClassifier* classifier, bool* ok) { // InitializationExpression :: (strong mode) // 'this' '.' IdentifierName '=' AssignmentExpression // 'this' '[' Expression ']' '=' AssignmentExpression @@ -3038,7 +3131,7 @@ ParserBase::ParseStrongInitializationExpression(bool* ok) { case Token::LBRACK: { Consume(Token::LBRACK); int pos = position(); - ExpressionT index = this->ParseExpression(true, CHECK_OK); + ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK); left = factory()->NewProperty(this_expr, index, pos); if (fni_ != NULL) { this->PushPropertyName(fni_, index); @@ -3072,7 +3165,8 @@ ParserBase::ParseStrongInitializationExpression(bool* ok) { Consume(Token::ASSIGN); left = this->MarkExpressionAsAssigned(left); - ExpressionT right = this->ParseAssignmentExpression(true, CHECK_OK); + ExpressionT right = + this->ParseAssignmentExpression(true, classifier, CHECK_OK); this->CheckAssigningFunctionLiteralToProperty(left, right); function_state_->AddProperty(); if (fni_ != NULL) { @@ -3100,7 +3194,8 @@ ParserBase::ParseStrongInitializationExpression(bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseStrongSuperCallExpression(bool* ok) { +ParserBase::ParseStrongSuperCallExpression( + ExpressionClassifier* classifier, bool* ok) { // SuperCallExpression :: (strong mode) // 'super' '(' ExpressionList ')' @@ -3117,7 +3212,7 @@ ParserBase::ParseStrongSuperCallExpression(bool* ok) { Scanner::Location spread_pos; typename Traits::Type::ExpressionList args = - ParseArguments(&spread_pos, CHECK_OK); + ParseArguments(&spread_pos, classifier, CHECK_OK); // TODO(rossberg): This doesn't work with arrow functions yet. if (!IsSubclassConstructor(function_state_->kind())) { @@ -3151,7 +3246,9 @@ ParserBase::ParseStrongSuperCallExpression(bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseSuperExpression(bool is_new, bool* ok) { +ParserBase::ParseSuperExpression(bool is_new, + ExpressionClassifier* classifier, + bool* ok) { Expect(Token::SUPER, CHECK_OK); // TODO(wingo): Does this actually work with lazily compiled arrows? @@ -3190,8 +3287,8 @@ ParserBase::ParseSuperExpression(bool is_new, bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseMemberExpressionContinuation(ExpressionT expression, - bool* ok) { +ParserBase::ParseMemberExpressionContinuation( + ExpressionT expression, ExpressionClassifier* classifier, bool* ok) { // Parses this part of MemberExpression: // ('[' Expression ']' | '.' Identifier | TemplateLiteral)* while (true) { @@ -3199,7 +3296,7 @@ ParserBase::ParseMemberExpressionContinuation(ExpressionT expression, case Token::LBRACK: { Consume(Token::LBRACK); int pos = position(); - ExpressionT index = this->ParseExpression(true, CHECK_OK); + ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK); expression = factory()->NewProperty(expression, index, pos); if (fni_ != NULL) { this->PushPropertyName(fni_, index); @@ -3231,7 +3328,8 @@ ParserBase::ParseMemberExpressionContinuation(ExpressionT expression, expression->AsFunctionLiteral()->set_parenthesized(); } } - expression = ParseTemplateLiteral(expression, pos, CHECK_OK); + expression = + ParseTemplateLiteral(expression, pos, classifier, CHECK_OK); break; } default: @@ -3343,7 +3441,7 @@ template typename ParserBase::ExpressionT ParserBase::ParseArrowFunctionLiteral( Scope* scope, const FormalParameterErrorLocations& error_locs, - bool has_rest, bool* ok) { + bool has_rest, ExpressionClassifier* classifier, bool* ok) { if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { // ASI inserts `;` after arrow parameters if a line terminator is found. // `=> ...` is never a valid expression, so report as syntax error. @@ -3389,7 +3487,8 @@ ParserBase::ParseArrowFunctionLiteral( // Single-expression body int pos = position(); parenthesized_function_ = false; - ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK); + ExpressionT expression = + ParseAssignmentExpression(true, classifier, CHECK_OK); body = this->NewStatementList(1, zone()); body->Add(factory()->NewReturnStatement(expression, pos), zone()); materialized_literal_count = function_state.materialized_literal_count(); @@ -3435,7 +3534,9 @@ ParserBase::ParseArrowFunctionLiteral( template typename ParserBase::ExpressionT -ParserBase::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) { +ParserBase::ParseTemplateLiteral(ExpressionT tag, int start, + ExpressionClassifier* classifier, + bool* ok) { // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal // text followed by a substitution expression), finalized by a single // TEMPLATE_TAIL. @@ -3487,7 +3588,7 @@ ParserBase::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) { } int expr_pos = peek_position(); - ExpressionT expression = this->ParseExpression(true, CHECK_OK); + ExpressionT expression = this->ParseExpression(true, classifier, CHECK_OK); Traits::AddTemplateExpression(&ts, expression); if (peek() != Token::RBRACE) { diff --git a/src/scanner.h b/src/scanner.h index 5162fbe..4d7411f 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -355,6 +355,14 @@ class Scanner { int beg_pos; int end_pos; + + bool inline operator==(const Location& other) const { + return beg_pos == other.beg_pos && end_pos == other.end_pos; + } + + bool inline operator!=(const Location& other) const { + return !(*this == other); + } }; // -1 is outside of the range of any real source code. -- 2.7.4