Introduce "expression classifier" to the parser.
authordslomov <dslomov@chromium.org>
Wed, 22 Apr 2015 12:35:05 +0000 (05:35 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 22 Apr 2015 12:34:51 +0000 (12:34 +0000)
R=marja@chromium.org,rossberg@chromium.org

Review URL: https://codereview.chromium.org/1065983005

Cr-Commit-Position: refs/heads/master@{#28005}

src/bootstrapper.cc
src/flag-definitions.h
src/parser.cc
src/preparser.cc
src/preparser.h
src/scanner.h

index cb9bdfa..1a5bfcf 100644 (file)
@@ -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<JSObject> 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++) {
index c749ec0..493f3b0 100644 (file)
@@ -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)                               \
index 2961a1a..b9ae09a 100644 (file)
@@ -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<Expression*>* args = ParseArguments(&spread_pos, CHECK_OK);
+  ExpressionClassifier classifier;
+  ZoneList<Expression*>* args =
+      ParseArguments(&spread_pos, &classifier, CHECK_OK);
+  // TODO(dslomov): report error if not a valid expression.
 
   DCHECK(!spread_pos.IsValid());
 
index caa383a..950f7b5 100644 (file)
@@ -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());
 
index 0d71d93..3632051 100644 (file)
@@ -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<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::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<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
 #define DUMMY )  // to make indentation work
 #undef DUMMY
 
+
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
+ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
+                                           bool* ok) {
   // PrimaryExpression ::
   //   'this'
   //   'null'
@@ -2094,19 +2154,19 @@ ParserBase<Traits>::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<Traits>::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<Traits>::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<Traits>::ParsePrimaryExpression(bool* ok) {
   return result;
 }
 
-// Precedence = 1
+
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::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 <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::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<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
-    bool* ok) {
+    ExpressionClassifier* classifier, bool* ok) {
   // ArrayLiteral ::
   //   '[' Expression? (',' Expression?)* ']'
 
@@ -2214,7 +2287,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::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<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::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<Traits>::ExpressionT ParserBase<Traits>::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<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
 
 template <class Traits>
 typename ParserBase<Traits>::ObjectLiteralPropertyT
-ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
-                                            bool in_class, bool has_extends,
-                                            bool is_static,
-                                            bool* is_computed_name,
-                                            bool* has_seen_constructor,
-                                            bool* ok) {
+ParserBase<Traits>::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<Traits>::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<Traits>::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<Traits>::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<Traits>::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<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
-    bool* ok) {
+    ExpressionClassifier* classifier, bool* ok) {
   // ObjectLiteral ::
   // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
 
@@ -2446,7 +2518,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::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<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
 
 template <class Traits>
 typename Traits::Type::ExpressionList ParserBase<Traits>::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<Traits>::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<Traits>::ParseArguments(
 // Precedence = 2
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
+ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
+                                              ExpressionClassifier* classifier,
+                                              bool* ok) {
   // AssignmentExpression ::
   //   ConditionalExpression
   //   ArrowFunction
@@ -2566,13 +2641,13 @@ ParserBase<Traits>::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<Traits>::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<Traits>::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<Traits>::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<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseYieldExpression(bool* ok) {
+ParserBase<Traits>::ParseYieldExpression(ExpressionClassifier* classifier,
+                                         bool* ok) {
   // YieldExpression ::
   //   'yield' ([no line terminator] '*'? AssignmentExpression)?
   int pos = peek_position();
@@ -2661,7 +2738,7 @@ ParserBase<Traits>::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<Traits>::ParseYieldExpression(bool* ok) {
 // Precedence = 3
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
+ParserBase<Traits>::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<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
 // Precedence >= 4
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
+ParserBase<Traits>::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<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
+ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
+                                         bool* ok) {
   // UnaryExpression ::
   //   PostfixExpression
   //   'delete' UnaryExpression
@@ -2771,7 +2856,7 @@ ParserBase<Traits>::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<Traits>::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<Traits>::ParseUnaryExpression(bool* ok) {
                                         position());
 
   } else {
-    return this->ParsePostfixExpression(ok);
+    return this->ParsePostfixExpression(classifier, ok);
   }
 }
 
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
+ParserBase<Traits>::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<Traits>::ParsePostfixExpression(bool* ok) {
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
+ParserBase<Traits>::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<Traits>::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<Traits>::ParseLeftHandSideExpression(bool* ok) {
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
+ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(
+    ExpressionClassifier* classifier, bool* ok) {
   // NewExpression ::
   //   ('new')+ MemberExpression
 
@@ -2943,15 +3033,15 @@ ParserBase<Traits>::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<Traits>::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<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
                                  new_pos);
   }
   // No 'new' or 'super' keyword.
-  return this->ParseMemberExpression(ok);
+  return this->ParseMemberExpression(classifier, ok);
 }
 
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberExpression(bool* ok) {
+ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
+                                          bool* ok) {
   // MemberExpression ::
   //   (PrimaryExpression | FunctionLiteral | ClassLiteral)
   //     ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
@@ -3008,19 +3100,20 @@ ParserBase<Traits>::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 <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseStrongInitializationExpression(bool* ok) {
+ParserBase<Traits>::ParseStrongInitializationExpression(
+    ExpressionClassifier* classifier, bool* ok) {
   // InitializationExpression ::  (strong mode)
   //  'this' '.' IdentifierName '=' AssignmentExpression
   //  'this' '[' Expression ']' '=' AssignmentExpression
@@ -3038,7 +3131,7 @@ ParserBase<Traits>::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<Traits>::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<Traits>::ParseStrongInitializationExpression(bool* ok) {
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseStrongSuperCallExpression(bool* ok) {
+ParserBase<Traits>::ParseStrongSuperCallExpression(
+    ExpressionClassifier* classifier, bool* ok) {
   // SuperCallExpression ::  (strong mode)
   //  'super' '(' ExpressionList ')'
 
@@ -3117,7 +3212,7 @@ ParserBase<Traits>::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<Traits>::ParseStrongSuperCallExpression(bool* ok) {
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseSuperExpression(bool is_new, bool* ok) {
+ParserBase<Traits>::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<Traits>::ParseSuperExpression(bool is_new, bool* ok) {
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
-                                                      bool* ok) {
+ParserBase<Traits>::ParseMemberExpressionContinuation(
+    ExpressionT expression, ExpressionClassifier* classifier, bool* ok) {
   // Parses this part of MemberExpression:
   // ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
   while (true) {
@@ -3199,7 +3296,7 @@ ParserBase<Traits>::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<Traits>::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 <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::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<Traits>::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<Traits>::ParseArrowFunctionLiteral(
 
 template <typename Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
+ParserBase<Traits>::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<Traits>::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) {
index 5162fbe..4d7411f 100644 (file)
@@ -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.