// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_PARSING_PREPARSER_H
#define V8_PARSING_PREPARSER_H

#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/preparse-data.h"
#include "src/pending-compilation-error-handler.h"

namespace v8 {
namespace internal {

// Whereas the Parser generates AST during the recursive descent,
// the PreParser doesn't create a tree. Instead, it passes around minimal
// data objects (PreParserExpression, PreParserIdentifier etc.) which contain
// just enough data for the upper layer functions. PreParserFactory is
// responsible for creating these dummy objects. It provides a similar kind of
// interface as AstNodeFactory, so ParserBase doesn't need to care which one is
// used.

class ProducedPreParsedScopeData;

class PreParserIdentifier {
 public:
  PreParserIdentifier() : type_(kUnknownIdentifier) {}
  static PreParserIdentifier Default() {
    return PreParserIdentifier(kUnknownIdentifier);
  }
  static PreParserIdentifier Empty() {
    return PreParserIdentifier(kEmptyIdentifier);
  }
  static PreParserIdentifier Eval() {
    return PreParserIdentifier(kEvalIdentifier);
  }
  static PreParserIdentifier Arguments() {
    return PreParserIdentifier(kArgumentsIdentifier);
  }
  static PreParserIdentifier Undefined() {
    return PreParserIdentifier(kUndefinedIdentifier);
  }
  static PreParserIdentifier FutureReserved() {
    return PreParserIdentifier(kFutureReservedIdentifier);
  }
  static PreParserIdentifier FutureStrictReserved() {
    return PreParserIdentifier(kFutureStrictReservedIdentifier);
  }
  static PreParserIdentifier Let() {
    return PreParserIdentifier(kLetIdentifier);
  }
  static PreParserIdentifier Static() {
    return PreParserIdentifier(kStaticIdentifier);
  }
  static PreParserIdentifier Yield() {
    return PreParserIdentifier(kYieldIdentifier);
  }
  static PreParserIdentifier Prototype() {
    return PreParserIdentifier(kPrototypeIdentifier);
  }
  static PreParserIdentifier Constructor() {
    return PreParserIdentifier(kConstructorIdentifier);
  }
  static PreParserIdentifier Enum() {
    return PreParserIdentifier(kEnumIdentifier);
  }
  static PreParserIdentifier Await() {
    return PreParserIdentifier(kAwaitIdentifier);
  }
  static PreParserIdentifier Async() {
    return PreParserIdentifier(kAsyncIdentifier);
  }
  static PreParserIdentifier Name() {
    return PreParserIdentifier(kNameIdentifier);
  }
  bool IsEmpty() const { return type_ == kEmptyIdentifier; }
  bool IsEval() const { return type_ == kEvalIdentifier; }
  bool IsArguments() const { return type_ == kArgumentsIdentifier; }
  bool IsEvalOrArguments() const { return IsEval() || IsArguments(); }
  bool IsUndefined() const { return type_ == kUndefinedIdentifier; }
  bool IsLet() const { return type_ == kLetIdentifier; }
  bool IsStatic() const { return type_ == kStaticIdentifier; }
  bool IsYield() const { return type_ == kYieldIdentifier; }
  bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
  bool IsConstructor() const { return type_ == kConstructorIdentifier; }
  bool IsEnum() const { return type_ == kEnumIdentifier; }
  bool IsAwait() const { return type_ == kAwaitIdentifier; }
  bool IsName() const { return type_ == kNameIdentifier; }

  // Allow identifier->name()[->length()] to work. The preparser
  // does not need the actual positions/lengths of the identifiers.
  const PreParserIdentifier* operator->() const { return this; }
  const PreParserIdentifier raw_name() const { return *this; }

  int position() const { return 0; }
  int length() const { return 0; }

 private:
  enum Type {
    kEmptyIdentifier,
    kUnknownIdentifier,
    kFutureReservedIdentifier,
    kFutureStrictReservedIdentifier,
    kLetIdentifier,
    kStaticIdentifier,
    kYieldIdentifier,
    kEvalIdentifier,
    kArgumentsIdentifier,
    kUndefinedIdentifier,
    kPrototypeIdentifier,
    kConstructorIdentifier,
    kEnumIdentifier,
    kAwaitIdentifier,
    kAsyncIdentifier,
    kNameIdentifier
  };

  explicit PreParserIdentifier(Type type) : type_(type), string_(nullptr) {}
  Type type_;
  // Only non-nullptr when PreParser.track_unresolved_variables_ is true.
  const AstRawString* string_;
  friend class PreParserExpression;
  friend class PreParser;
  friend class PreParserFactory;
};


class PreParserExpression {
 public:
  PreParserExpression()
      : code_(TypeField::encode(kEmpty)), variables_(nullptr) {}

  static PreParserExpression Empty() { return PreParserExpression(); }

  static PreParserExpression Default(
      ZoneList<VariableProxy*>* variables = nullptr) {
    return PreParserExpression(TypeField::encode(kExpression), variables);
  }

  static PreParserExpression Spread(PreParserExpression expression) {
    return PreParserExpression(TypeField::encode(kSpreadExpression),
                               expression.variables_);
  }

  static PreParserExpression FromIdentifier(PreParserIdentifier id,
                                            VariableProxy* variable,
                                            Zone* zone) {
    PreParserExpression expression(TypeField::encode(kIdentifierExpression) |
                                   IdentifierTypeField::encode(id.type_));
    expression.AddVariable(variable, zone);
    return expression;
  }

  static PreParserExpression BinaryOperation(PreParserExpression left,
                                             Token::Value op,
                                             PreParserExpression right,
                                             Zone* zone) {
    if (op == Token::COMMA) {
      // Possibly an arrow function parameter list.
      if (left.variables_ == nullptr) {
        return PreParserExpression(TypeField::encode(kExpression),
                                   right.variables_);
      }
      if (right.variables_ != nullptr) {
        for (auto variable : *right.variables_) {
          left.variables_->Add(variable, zone);
        }
      }
      return PreParserExpression(TypeField::encode(kExpression),
                                 left.variables_);
    }
    return PreParserExpression(TypeField::encode(kExpression));
  }

  static PreParserExpression Assignment(ZoneList<VariableProxy*>* variables) {
    return PreParserExpression(TypeField::encode(kExpression) |
                                   ExpressionTypeField::encode(kAssignment),
                               variables);
  }

  static PreParserExpression NewTargetExpression() {
    return PreParserExpression(TypeField::encode(kExpression) |
                               ExpressionTypeField::encode(kNewTarget));
  }

  static PreParserExpression ObjectLiteral(
      ZoneList<VariableProxy*>* variables) {
    return PreParserExpression(TypeField::encode(kObjectLiteralExpression),
                               variables);
  }

  static PreParserExpression ArrayLiteral(ZoneList<VariableProxy*>* variables) {
    return PreParserExpression(TypeField::encode(kArrayLiteralExpression),
                               variables);
  }

  static PreParserExpression StringLiteral() {
    return PreParserExpression(TypeField::encode(kStringLiteralExpression));
  }

  static PreParserExpression UseStrictStringLiteral() {
    return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
                               IsUseStrictField::encode(true));
  }

  static PreParserExpression UseAsmStringLiteral() {
    return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
                               IsUseAsmField::encode(true));
  }

  static PreParserExpression This(ZoneList<VariableProxy*>* variables) {
    return PreParserExpression(TypeField::encode(kExpression) |
                                   ExpressionTypeField::encode(kThisExpression),
                               variables);
  }

  static PreParserExpression ThisProperty() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kThisPropertyExpression));
  }

  static PreParserExpression Property() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kPropertyExpression));
  }

  static PreParserExpression Call() {
    return PreParserExpression(TypeField::encode(kExpression) |
                               ExpressionTypeField::encode(kCallExpression));
  }

  static PreParserExpression CallEval() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kCallEvalExpression));
  }

  static PreParserExpression SuperCallReference() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kSuperCallReference));
  }

  static PreParserExpression NoTemplateTag() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kNoTemplateTagExpression));
  }

  bool IsEmpty() const { return TypeField::decode(code_) == kEmpty; }

  bool IsIdentifier() const {
    return TypeField::decode(code_) == kIdentifierExpression;
  }

  PreParserIdentifier AsIdentifier() const {
    DCHECK(IsIdentifier());
    return PreParserIdentifier(IdentifierTypeField::decode(code_));
  }

  bool IsAssignment() const {
    return TypeField::decode(code_) == kExpression &&
           ExpressionTypeField::decode(code_) == kAssignment;
  }

  bool IsObjectLiteral() const {
    return TypeField::decode(code_) == kObjectLiteralExpression;
  }

  bool IsArrayLiteral() const {
    return TypeField::decode(code_) == kArrayLiteralExpression;
  }

  bool IsStringLiteral() const {
    return TypeField::decode(code_) == kStringLiteralExpression;
  }

  bool IsUseStrictLiteral() const {
    return TypeField::decode(code_) == kStringLiteralExpression &&
           IsUseStrictField::decode(code_);
  }

  bool IsUseAsmLiteral() const {
    return TypeField::decode(code_) == kStringLiteralExpression &&
           IsUseAsmField::decode(code_);
  }

  bool IsThis() const {
    return TypeField::decode(code_) == kExpression &&
           ExpressionTypeField::decode(code_) == kThisExpression;
  }

  bool IsThisProperty() const {
    return TypeField::decode(code_) == kExpression &&
           ExpressionTypeField::decode(code_) == kThisPropertyExpression;
  }

  bool IsProperty() const {
    return TypeField::decode(code_) == kExpression &&
           (ExpressionTypeField::decode(code_) == kPropertyExpression ||
            ExpressionTypeField::decode(code_) == kThisPropertyExpression);
  }

  bool IsCall() const {
    return TypeField::decode(code_) == kExpression &&
           (ExpressionTypeField::decode(code_) == kCallExpression ||
            ExpressionTypeField::decode(code_) == kCallEvalExpression);
  }

  bool IsSuperCallReference() const {
    return TypeField::decode(code_) == kExpression &&
           ExpressionTypeField::decode(code_) == kSuperCallReference;
  }

  bool IsValidReferenceExpression() const {
    return IsIdentifier() || IsProperty();
  }

  // At the moment PreParser doesn't track these expression types.
  bool IsFunctionLiteral() const { return false; }
  bool IsCallNew() const { return false; }

  bool IsNoTemplateTag() const {
    return TypeField::decode(code_) == kExpression &&
           ExpressionTypeField::decode(code_) == kNoTemplateTagExpression;
  }

  bool IsSpread() const {
    return TypeField::decode(code_) == kSpreadExpression;
  }

  PreParserExpression AsFunctionLiteral() { return *this; }

  // Dummy implementation for making expression->somefunc() work in both Parser
  // and PreParser.
  PreParserExpression* operator->() { return this; }

  // More dummy implementations of things PreParser doesn't need to track:
  void SetShouldEagerCompile() {}
  void set_should_be_used_once_hint() {}

  int position() const { return kNoSourcePosition; }
  void set_function_token_position(int position) {}

 private:
  enum Type {
    kEmpty,
    kExpression,
    kIdentifierExpression,
    kStringLiteralExpression,
    kSpreadExpression,
    kObjectLiteralExpression,
    kArrayLiteralExpression
  };

  enum ExpressionType {
    kThisExpression,
    kThisPropertyExpression,
    kPropertyExpression,
    kCallExpression,
    kCallEvalExpression,
    kSuperCallReference,
    kNoTemplateTagExpression,
    kAssignment,
    kNewTarget
  };

  explicit PreParserExpression(uint32_t expression_code,
                               ZoneList<VariableProxy*>* variables = nullptr)
      : code_(expression_code), variables_(variables) {}

  void AddVariable(VariableProxy* variable, Zone* zone) {
    if (variable == nullptr) {
      return;
    }
    if (variables_ == nullptr) {
      variables_ = new (zone) ZoneList<VariableProxy*>(1, zone);
    }
    variables_->Add(variable, zone);
  }

  // The first three bits are for the Type.
  typedef BitField<Type, 0, 3> TypeField;

  // The high order bit applies only to nodes which would inherit from the
  // Expression ASTNode --- This is by necessity, due to the fact that
  // Expression nodes may be represented as multiple Types, not exclusively
  // through kExpression.
  // TODO(caitp, adamk): clean up PreParserExpression bitfields.
  typedef BitField<bool, 31, 1> ParenthesizedField;

  // The rest of the bits are interpreted depending on the value
  // of the Type field, so they can share the storage.
  typedef BitField<ExpressionType, TypeField::kNext, 4> ExpressionTypeField;
  typedef BitField<bool, TypeField::kNext, 1> IsUseStrictField;
  typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseAsmField;
  typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10>
      IdentifierTypeField;
  typedef BitField<bool, TypeField::kNext, 1> HasCoverInitializedNameField;

  uint32_t code_;
  // If the PreParser is used in the variable tracking mode, PreParserExpression
  // accumulates variables in that expression.
  ZoneList<VariableProxy*>* variables_;

  friend class PreParser;
  friend class PreParserFactory;
  template <typename T>
  friend class PreParserList;
};


// The pre-parser doesn't need to build lists of expressions, identifiers, or
// the like. If the PreParser is used in variable tracking mode, it needs to
// build lists of variables though.
template <typename T>
class PreParserList {
 public:
  // These functions make list->Add(some_expression) work (and do nothing).
  PreParserList() : length_(0), variables_(nullptr) {}
  PreParserList* operator->() { return this; }
  void Add(const T& element, Zone* zone);
  int length() const { return length_; }
  static PreParserList Null() { return PreParserList(-1); }
  bool IsNull() const { return length_ == -1; }
  void Set(int index, const T& element) {}

 private:
  explicit PreParserList(int n) : length_(n), variables_(nullptr) {}
  int length_;
  ZoneList<VariableProxy*>* variables_;

  friend class PreParser;
  friend class PreParserFactory;
};

template <>
inline void PreParserList<PreParserExpression>::Add(
    const PreParserExpression& expression, Zone* zone) {
  if (expression.variables_ != nullptr) {
    DCHECK(FLAG_lazy_inner_functions);
    DCHECK(zone != nullptr);
    if (variables_ == nullptr) {
      variables_ = new (zone) ZoneList<VariableProxy*>(1, zone);
    }
    for (auto identifier : (*expression.variables_)) {
      variables_->Add(identifier, zone);
    }
  }
  ++length_;
}

template <typename T>
void PreParserList<T>::Add(const T& element, Zone* zone) {
  ++length_;
}

typedef PreParserList<PreParserExpression> PreParserExpressionList;

class PreParserStatement;
typedef PreParserList<PreParserStatement> PreParserStatementList;

class PreParserStatement {
 public:
  static PreParserStatement Default() {
    return PreParserStatement(kUnknownStatement);
  }

  static PreParserStatement Null() {
    return PreParserStatement(kNullStatement);
  }

  static PreParserStatement Empty() {
    return PreParserStatement(kEmptyStatement);
  }

  static PreParserStatement Jump() {
    return PreParserStatement(kJumpStatement);
  }

  // Creates expression statement from expression.
  // Preserves being an unparenthesized string literal, possibly
  // "use strict".
  static PreParserStatement ExpressionStatement(
      PreParserExpression expression) {
    if (expression.IsUseStrictLiteral()) {
      return PreParserStatement(kUseStrictExpressionStatement);
    }
    if (expression.IsUseAsmLiteral()) {
      return PreParserStatement(kUseAsmExpressionStatement);
    }
    if (expression.IsStringLiteral()) {
      return PreParserStatement(kStringLiteralExpressionStatement);
    }
    return Default();
  }

  bool IsStringLiteral() {
    return code_ == kStringLiteralExpressionStatement || IsUseStrictLiteral() ||
           IsUseAsmLiteral();
  }

  bool IsUseStrictLiteral() {
    return code_ == kUseStrictExpressionStatement;
  }

  bool IsUseAsmLiteral() { return code_ == kUseAsmExpressionStatement; }

  bool IsJumpStatement() {
    return code_ == kJumpStatement;
  }

  bool IsNullStatement() { return code_ == kNullStatement; }

  bool IsEmptyStatement() { return code_ == kEmptyStatement; }

  // Dummy implementation for making statement->somefunc() work in both Parser
  // and PreParser.
  PreParserStatement* operator->() { return this; }

  PreParserStatementList statements() { return PreParserStatementList(); }
  void set_scope(Scope* scope) {}
  void Initialize(PreParserExpression cond, PreParserStatement body,
                  const SourceRange& body_range = {}) {}
  void Initialize(PreParserStatement init, PreParserExpression cond,
                  PreParserStatement next, PreParserStatement body,
                  const SourceRange& body_range = {}) {}

 private:
  enum Type {
    kNullStatement,
    kEmptyStatement,
    kUnknownStatement,
    kJumpStatement,
    kStringLiteralExpressionStatement,
    kUseStrictExpressionStatement,
    kUseAsmExpressionStatement,
  };

  explicit PreParserStatement(Type code) : code_(code) {}
  Type code_;
};


class PreParserFactory {
 public:
  explicit PreParserFactory(AstValueFactory* ast_value_factory, Zone* zone)
      : ast_node_factory_(ast_value_factory, zone), zone_(zone) {}

  void set_zone(Zone* zone) {
    ast_node_factory_.set_zone(zone);
    zone_ = zone;
  }

  AstNodeFactory* ast_node_factory() { return &ast_node_factory_; }

  PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
                                       int pos) {
    // This is needed for object literal property names. Property names are
    // normalized to string literals during object literal parsing.
    PreParserExpression expression = PreParserExpression::Default();
    if (identifier.string_ != nullptr) {
      DCHECK(FLAG_lazy_inner_functions);
      VariableProxy* variable = ast_node_factory_.NewVariableProxy(
          identifier.string_, NORMAL_VARIABLE);
      expression.AddVariable(variable, zone_);
    }
    return expression;
  }
  PreParserExpression NewNumberLiteral(double number,
                                       int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewUndefinedLiteral(int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
                                       int js_flags, int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewArrayLiteral(PreParserExpressionList values,
                                      int first_spread_index, int pos) {
    return PreParserExpression::ArrayLiteral(values.variables_);
  }
  PreParserExpression NewClassLiteralProperty(PreParserExpression key,
                                              PreParserExpression value,
                                              ClassLiteralProperty::Kind kind,
                                              bool is_static,
                                              bool is_computed_name) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
                                               PreParserExpression value,
                                               ObjectLiteralProperty::Kind kind,
                                               bool is_computed_name) {
    return PreParserExpression::Default(value.variables_);
  }
  PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
                                               PreParserExpression value,
                                               bool is_computed_name) {
    return PreParserExpression::Default(value.variables_);
  }
  PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
                                       int boilerplate_properties, int pos,
                                       bool has_rest_property) {
    return PreParserExpression::ObjectLiteral(properties.variables_);
  }
  PreParserExpression NewVariableProxy(void* variable) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewProperty(PreParserExpression obj,
                                  PreParserExpression key,
                                  int pos) {
    if (obj.IsThis()) {
      return PreParserExpression::ThisProperty();
    }
    return PreParserExpression::Property();
  }
  PreParserExpression NewUnaryOperation(Token::Value op,
                                        PreParserExpression expression,
                                        int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewBinaryOperation(Token::Value op,
                                         PreParserExpression left,
                                         PreParserExpression right, int pos) {
    return PreParserExpression::BinaryOperation(left, op, right, zone_);
  }
  PreParserExpression NewCompareOperation(Token::Value op,
                                          PreParserExpression left,
                                          PreParserExpression right, int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewRewritableExpression(PreParserExpression expression) {
    return expression;
  }
  PreParserExpression NewAssignment(Token::Value op,
                                    PreParserExpression left,
                                    PreParserExpression right,
                                    int pos) {
    // Identifiers need to be tracked since this might be a parameter with a
    // default value inside an arrow function parameter list.
    return PreParserExpression::Assignment(left.variables_);
  }
  PreParserExpression NewSuspend(PreParserExpression expression, int pos,
                                 Suspend::OnAbruptResume on_abrupt_resume,
                                 SuspendFlags flags) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewAwait(PreParserExpression expression, int pos,
                               SuspendFlags flags) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewConditional(PreParserExpression condition,
                                     PreParserExpression then_expression,
                                     PreParserExpression else_expression,
                                     int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewCountOperation(Token::Value op,
                                        bool is_prefix,
                                        PreParserExpression expression,
                                        int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewCall(
      PreParserExpression expression, PreParserExpressionList arguments,
      int pos, Call::PossiblyEval possibly_eval = Call::NOT_EVAL) {
    if (possibly_eval == Call::IS_POSSIBLY_EVAL) {
      DCHECK(expression.IsIdentifier() && expression.AsIdentifier().IsEval());
      return PreParserExpression::CallEval();
    }
    return PreParserExpression::Call();
  }
  PreParserExpression NewCallNew(PreParserExpression expression,
                                 PreParserExpressionList arguments,
                                 int pos) {
    return PreParserExpression::Default();
  }
  PreParserStatement NewReturnStatement(
      PreParserExpression expression, int pos,
      int continuation_pos = kNoSourcePosition) {
    return PreParserStatement::Jump();
  }
  PreParserStatement NewAsyncReturnStatement(
      PreParserExpression expression, int pos,
      int continuation_pos = kNoSourcePosition) {
    return PreParserStatement::Jump();
  }
  PreParserExpression NewFunctionLiteral(
      PreParserIdentifier name, Scope* scope, PreParserStatementList body,
      int expected_property_count, int parameter_count, int function_length,
      FunctionLiteral::ParameterFlag has_duplicate_parameters,
      FunctionLiteral::FunctionType function_type,
      FunctionLiteral::EagerCompileHint eager_compile_hint, int position,
      bool has_braces, int function_literal_id,
      ProducedPreParsedScopeData* produced_preparsed_scope_data = nullptr) {
    DCHECK_NULL(produced_preparsed_scope_data);
    return PreParserExpression::Default();
  }

  PreParserExpression NewSpread(PreParserExpression expression, int pos,
                                int expr_pos) {
    return PreParserExpression::Spread(expression);
  }

  PreParserExpression NewEmptyParentheses(int pos) {
    return PreParserExpression::Default();
  }

  PreParserStatement NewEmptyStatement(int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewBlock(ZoneList<const AstRawString*>* labels,
                              int capacity, bool ignore_completion_value,
                              int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewDebuggerStatement(int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewExpressionStatement(PreParserExpression expr, int pos) {
    return PreParserStatement::ExpressionStatement(expr);
  }

  PreParserStatement NewIfStatement(PreParserExpression condition,
                                    PreParserStatement then_statement,
                                    PreParserStatement else_statement, int pos,
                                    SourceRange then_range = {},
                                    SourceRange else_range = {}) {
    // This must return a jump statement iff both clauses are jump statements.
    return else_statement.IsJumpStatement() ? then_statement : else_statement;
  }

  PreParserStatement NewBreakStatement(
      PreParserStatement target, int pos,
      int continuation_pos = kNoSourcePosition) {
    return PreParserStatement::Jump();
  }

  PreParserStatement NewContinueStatement(
      PreParserStatement target, int pos,
      int continuation_pos = kNoSourcePosition) {
    return PreParserStatement::Jump();
  }

  PreParserStatement NewWithStatement(Scope* scope,
                                      PreParserExpression expression,
                                      PreParserStatement statement, int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewDoWhileStatement(ZoneList<const AstRawString*>* labels,
                                         int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewWhileStatement(ZoneList<const AstRawString*>* labels,
                                       int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewSwitchStatement(ZoneList<const AstRawString*>* labels,
                                        int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewCaseClause(PreParserExpression label,
                                   PreParserStatementList statements, int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewForStatement(ZoneList<const AstRawString*>* labels,
                                     int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewForEachStatement(ForEachStatement::VisitMode visit_mode,
                                         ZoneList<const AstRawString*>* labels,
                                         int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewForOfStatement(ZoneList<const AstRawString*>* labels,
                                       int pos) {
    return PreParserStatement::Default();
  }

  PreParserExpression NewCallRuntime(Runtime::FunctionId id,
                                     ZoneList<PreParserExpression>* arguments,
                                     int pos) {
    return PreParserExpression::Default();
  }

  PreParserExpression NewImportCallExpression(PreParserExpression args,
                                              int pos) {
    return PreParserExpression::Default();
  }

  // Return the object itself as AstVisitor and implement the needed
  // dummy method right in this class.
  PreParserFactory* visitor() { return this; }
  int* ast_properties() {
    static int dummy = 42;
    return &dummy;
  }

 private:
  // For creating VariableProxy objects (if
  // PreParser::track_unresolved_variables_ is used).
  AstNodeFactory ast_node_factory_;
  Zone* zone_;
};


struct PreParserFormalParameters : FormalParametersBase {
  struct Parameter : public ZoneObject {
    Parameter(ZoneList<VariableProxy*>* variables, bool is_rest)
        : variables_(variables), is_rest(is_rest) {}
    Parameter** next() { return &next_parameter; }
    Parameter* const* next() const { return &next_parameter; }

    ZoneList<VariableProxy*>* variables_;
    Parameter* next_parameter = nullptr;
    bool is_rest : 1;
  };
  explicit PreParserFormalParameters(DeclarationScope* scope)
      : FormalParametersBase(scope) {}

  ThreadedList<Parameter> params;
};


class PreParser;

class PreParserTarget {
 public:
  PreParserTarget(ParserBase<PreParser>* preparser,
                  PreParserStatement statement) {}
};

class PreParserTargetScope {
 public:
  explicit PreParserTargetScope(ParserBase<PreParser>* preparser) {}
};

template <>
struct ParserTypes<PreParser> {
  typedef ParserBase<PreParser> Base;
  typedef PreParser Impl;

  // Return types for traversing functions.
  typedef PreParserIdentifier Identifier;
  typedef PreParserExpression Expression;
  typedef PreParserExpression FunctionLiteral;
  typedef PreParserExpression ObjectLiteralProperty;
  typedef PreParserExpression ClassLiteralProperty;
  typedef PreParserExpression Suspend;
  typedef PreParserExpression Await;
  typedef PreParserExpressionList ExpressionList;
  typedef PreParserExpressionList ObjectPropertyList;
  typedef PreParserExpressionList ClassPropertyList;
  typedef PreParserFormalParameters FormalParameters;
  typedef PreParserStatement Statement;
  typedef PreParserStatementList StatementList;
  typedef PreParserStatement Block;
  typedef PreParserStatement BreakableStatement;
  typedef PreParserStatement IterationStatement;

  // For constructing objects returned by the traversing functions.
  typedef PreParserFactory Factory;

  typedef PreParserTarget Target;
  typedef PreParserTargetScope TargetScope;
};


// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparse-data-format.h for the data format.

// The PreParser checks that the syntax follows the grammar for JavaScript,
// and collects some information about the program along the way.
// The grammar check is only performed in order to understand the program
// sufficiently to deduce some information about it, that can be used
// to speed up later parsing. Finding errors is not the goal of pre-parsing,
// rather it is to speed up properly written and correct programs.
// That means that contextual checks (like a label being declared where
// it is used) are generally omitted.
class PreParser : public ParserBase<PreParser> {
  friend class ParserBase<PreParser>;
  friend class v8::internal::ExpressionClassifier<ParserTypes<PreParser>>;

 public:
  typedef PreParserIdentifier Identifier;
  typedef PreParserExpression Expression;
  typedef PreParserStatement Statement;

  enum PreParseResult {
    kPreParseStackOverflow,
    kPreParseAbort,
    kPreParseSuccess
  };

  PreParser(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
            AstValueFactory* ast_value_factory,
            PendingCompilationErrorHandler* pending_error_handler,
            RuntimeCallStats* runtime_call_stats,
            bool parsing_on_main_thread = true)
      : ParserBase<PreParser>(zone, scanner, stack_limit, nullptr,
                              ast_value_factory, runtime_call_stats,
                              parsing_on_main_thread),
        use_counts_(nullptr),
        track_unresolved_variables_(false),
        pending_error_handler_(pending_error_handler),
        produced_preparsed_scope_data_(nullptr) {}

  static bool IsPreParser() { return true; }

  PreParserLogger* logger() { return &log_; }

  // Pre-parse the program from the character stream; returns true on
  // success (even if parsing failed, the pre-parse data successfully
  // captured the syntax error), and false if a stack-overflow happened
  // during parsing.
  PreParseResult PreParseProgram(bool is_module = false);

  // Parses a single function literal, from the opening parentheses before
  // parameters to the closing brace after the body.
  // Returns a FunctionEntry describing the body of the function in enough
  // detail that it can be lazily compiled.
  // The scanner is expected to have matched the "function" or "function*"
  // keyword and parameters, and have consumed the initial '{'.
  // At return, unless an error occurred, the scanner is positioned before the
  // the final '}'.
  PreParseResult PreParseFunction(
      const AstRawString* function_name, FunctionKind kind,
      FunctionLiteral::FunctionType function_type,
      DeclarationScope* function_scope, bool parsing_module,
      bool track_unresolved_variables, bool may_abort, int* use_counts,
      ProducedPreParsedScopeData** produced_preparser_scope_data);

  ProducedPreParsedScopeData* produced_preparsed_scope_data() const {
    return produced_preparsed_scope_data_;
  }

  void set_produced_preparsed_scope_data(
      ProducedPreParsedScopeData* produced_preparsed_scope_data) {
    produced_preparsed_scope_data_ = produced_preparsed_scope_data;
  }

 private:
  // These types form an algebra over syntactic categories that is just
  // rich enough to let us recognize and propagate the constructs that
  // are either being counted in the preparser data, or is important
  // to throw the correct syntax error exceptions.

  // All ParseXXX functions take as the last argument an *ok parameter
  // which is set to false if parsing failed; it is unchanged otherwise.
  // By making the 'exception handling' explicit, we are forced to check
  // for failure at the call sites.

  // Indicates that we won't switch from the preparser to the preparser; we'll
  // just stay where we are.
  bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; }
  bool parse_lazily() const { return false; }

  V8_INLINE LazyParsingResult
  SkipFunction(const AstRawString* name, FunctionKind kind,
               FunctionLiteral::FunctionType function_type,
               DeclarationScope* function_scope, int* num_parameters,
               ProducedPreParsedScopeData** produced_preparsed_scope_data,
               bool is_inner_function, bool may_abort, bool* ok) {
    UNREACHABLE();
  }
  Expression ParseFunctionLiteral(
      Identifier name, Scanner::Location function_name_location,
      FunctionNameValidity function_name_validity, FunctionKind kind,
      int function_token_pos, FunctionLiteral::FunctionType function_type,
      LanguageMode language_mode, bool* ok);
  LazyParsingResult ParseStatementListAndLogFunction(
      PreParserFormalParameters* formals, bool maybe_abort, bool* ok);

  struct TemplateLiteralState {};

  V8_INLINE TemplateLiteralState OpenTemplateLiteral(int pos) {
    return TemplateLiteralState();
  }
  V8_INLINE void AddTemplateExpression(TemplateLiteralState* state,
                                       PreParserExpression expression) {}
  V8_INLINE void AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
                                 bool tail) {}
  V8_INLINE PreParserExpression CloseTemplateLiteral(
      TemplateLiteralState* state, int start, PreParserExpression tag);
  V8_INLINE void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}

  V8_INLINE void SetLanguageMode(Scope* scope, LanguageMode mode) {
    scope->SetLanguageMode(mode);
  }
  V8_INLINE void SetAsmModule() {}

  V8_INLINE void MarkCollectedTailCallExpressions() {}
  V8_INLINE void MarkTailPosition(PreParserExpression expression) {}

  V8_INLINE PreParserExpression SpreadCall(PreParserExpression function,
                                           PreParserExpressionList args,
                                           int pos,
                                           Call::PossiblyEval possibly_eval);
  V8_INLINE PreParserExpression SpreadCallNew(PreParserExpression function,
                                              PreParserExpressionList args,
                                              int pos);

  V8_INLINE void RewriteDestructuringAssignments() {}

  V8_INLINE PreParserExpression RewriteExponentiation(PreParserExpression left,
                                                      PreParserExpression right,
                                                      int pos) {
    return left;
  }
  V8_INLINE PreParserExpression RewriteAssignExponentiation(
      PreParserExpression left, PreParserExpression right, int pos) {
    return left;
  }

  V8_INLINE void PrepareAsyncFunctionBody(PreParserStatementList body,
                                          FunctionKind kind, int pos) {}
  V8_INLINE void RewriteAsyncFunctionBody(PreParserStatementList body,
                                          PreParserStatement block,
                                          PreParserExpression return_value,
                                          bool* ok) {}
  V8_INLINE PreParserExpression RewriteYieldStar(PreParserExpression expression,
                                                 int pos) {
    return PreParserExpression::Default();
  }
  V8_INLINE void RewriteNonPattern(bool* ok) { ValidateExpression(ok); }

  void DeclareAndInitializeVariables(
      PreParserStatement block,
      const DeclarationDescriptor* declaration_descriptor,
      const DeclarationParsingResult::Declaration* declaration,
      ZoneList<const AstRawString*>* names, bool* ok);

  V8_INLINE ZoneList<const AstRawString*>* DeclareLabel(
      ZoneList<const AstRawString*>* labels, PreParserExpression expr,
      bool* ok) {
    DCHECK(!expr.AsIdentifier().IsEnum());
    DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait());
    DCHECK(IsIdentifier(expr));
    return labels;
  }

  // TODO(nikolaos): The preparser currently does not keep track of labels.
  V8_INLINE bool ContainsLabel(ZoneList<const AstRawString*>* labels,
                               PreParserIdentifier label) {
    return false;
  }

  V8_INLINE PreParserExpression RewriteReturn(PreParserExpression return_value,
                                              int pos) {
    return return_value;
  }
  V8_INLINE PreParserStatement RewriteSwitchStatement(
      PreParserExpression tag, PreParserStatement switch_statement,
      PreParserStatementList cases, Scope* scope) {
    return PreParserStatement::Default();
  }

  V8_INLINE void RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {
    if (track_unresolved_variables_) {
      const AstRawString* catch_name = catch_info->name.string_;
      if (catch_name == nullptr) {
        catch_name = ast_value_factory()->dot_catch_string();
      }
      // Unlike in the parser, we need to declare the catch variable as LET
      // variable, so that it won't get hoisted out of the scope. (Parser uses
      // DeclareLocal instead of DeclareVariable to prevent hoisting.) Another
      // solution would've been to add DeclareLocalName just for this purpose.
      catch_info->scope->DeclareVariableName(catch_name, LET);

      if (catch_info->pattern.variables_ != nullptr) {
        for (auto variable : *catch_info->pattern.variables_) {
          scope()->DeclareVariableName(variable->raw_name(), LET);
        }
      }
    }
  }

  V8_INLINE void ValidateCatchBlock(const CatchInfo& catch_info, bool* ok) {}
  V8_INLINE PreParserStatement RewriteTryStatement(
      PreParserStatement try_block, PreParserStatement catch_block,
      const SourceRange& catch_range, PreParserStatement finally_block,
      const SourceRange& finally_range, const CatchInfo& catch_info, int pos) {
    return PreParserStatement::Default();
  }

  V8_INLINE void ParseAndRewriteGeneratorFunctionBody(
      int pos, FunctionKind kind, PreParserStatementList body, bool* ok) {
    ParseStatementList(body, Token::RBRACE, ok);
  }
  V8_INLINE void ParseAndRewriteAsyncGeneratorFunctionBody(
      int pos, FunctionKind kind, PreParserStatementList body, bool* ok) {
    ParseStatementList(body, Token::RBRACE, ok);
  }
  V8_INLINE void CreateFunctionNameAssignment(
      const AstRawString* function_name,
      FunctionLiteral::FunctionType function_type,
      DeclarationScope* function_scope) {
    if (track_unresolved_variables_ &&
        function_type == FunctionLiteral::kNamedExpression) {
      if (function_scope->LookupLocal(function_name) == nullptr) {
        DCHECK_EQ(function_scope, scope());
        Variable* fvar = function_scope->DeclareFunctionVar(function_name);
        fvar->set_is_used();
      }
    }
  }

  V8_INLINE void CreateFunctionNameAssignment(
      PreParserIdentifier function_name, int pos,
      FunctionLiteral::FunctionType function_type,
      DeclarationScope* function_scope, PreParserStatementList result,
      int index) {
    CreateFunctionNameAssignment(function_name.string_, function_type,
                                 function_scope);
  }

  V8_INLINE PreParserExpression RewriteDoExpression(PreParserStatement body,
                                                    int pos, bool* ok) {
    return PreParserExpression::Default();
  }

  // TODO(nikolaos): The preparser currently does not keep track of labels
  // and targets.
  V8_INLINE PreParserStatement LookupBreakTarget(PreParserIdentifier label,
                                                 bool* ok) {
    return PreParserStatement::Default();
  }
  V8_INLINE PreParserStatement LookupContinueTarget(PreParserIdentifier label,
                                                    bool* ok) {
    return PreParserStatement::Default();
  }

  V8_INLINE PreParserStatement DeclareFunction(
      PreParserIdentifier variable_name, PreParserExpression function,
      VariableMode mode, int pos, bool is_sloppy_block_function,
      ZoneList<const AstRawString*>* names, bool* ok) {
    DCHECK_NULL(names);
    if (variable_name.string_ != nullptr) {
      DCHECK(track_unresolved_variables_);
      scope()->DeclareVariableName(variable_name.string_, mode);
      if (is_sloppy_block_function) {
        GetDeclarationScope()->DeclareSloppyBlockFunction(variable_name.string_,
                                                          scope());
      }
    }
    return Statement::Default();
  }

  V8_INLINE PreParserStatement
  DeclareClass(PreParserIdentifier variable_name, PreParserExpression value,
               ZoneList<const AstRawString*>* names, int class_token_pos,
               int end_pos, bool* ok) {
    // Preparser shouldn't be used in contexts where we need to track the names.
    DCHECK_NULL(names);
    if (variable_name.string_ != nullptr) {
      DCHECK(track_unresolved_variables_);
      scope()->DeclareVariableName(variable_name.string_, LET);
    }
    return PreParserStatement::Default();
  }
  V8_INLINE void DeclareClassVariable(PreParserIdentifier name,
                                      ClassInfo* class_info,
                                      int class_token_pos, bool* ok) {
    if (name.string_ != nullptr) {
      DCHECK(track_unresolved_variables_);
      scope()->DeclareVariableName(name.string_, CONST);
    }
  }
  V8_INLINE void DeclareClassProperty(PreParserIdentifier class_name,
                                      PreParserExpression property,
                                      ClassLiteralProperty::Kind kind,
                                      bool is_static, bool is_constructor,
                                      ClassInfo* class_info, bool* ok) {
  }
  V8_INLINE PreParserExpression RewriteClassLiteral(Scope* scope,
                                                    PreParserIdentifier name,
                                                    ClassInfo* class_info,
                                                    int pos, int end_pos,
                                                    bool* ok) {
    bool has_default_constructor = !class_info->has_seen_constructor;
    // Account for the default constructor.
    if (has_default_constructor) GetNextFunctionLiteralId();
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserStatement DeclareNative(PreParserIdentifier name, int pos,
                                             bool* ok) {
    return PreParserStatement::Default();
  }

  V8_INLINE void QueueDestructuringAssignmentForRewriting(
      PreParserExpression assignment) {}
  V8_INLINE void QueueNonPatternForRewriting(PreParserExpression expr,
                                             bool* ok) {}

  // Helper functions for recursive descent.
  V8_INLINE bool IsEval(PreParserIdentifier identifier) const {
    return identifier.IsEval();
  }

  V8_INLINE bool IsArguments(PreParserIdentifier identifier) const {
    return identifier.IsArguments();
  }

  V8_INLINE bool IsEvalOrArguments(PreParserIdentifier identifier) const {
    return identifier.IsEvalOrArguments();
  }

  V8_INLINE bool IsUndefined(PreParserIdentifier identifier) const {
    return identifier.IsUndefined();
  }

  V8_INLINE bool IsAwait(PreParserIdentifier identifier) const {
    return identifier.IsAwait();
  }

  // Returns true if the expression is of type "this.foo".
  V8_INLINE static bool IsThisProperty(PreParserExpression expression) {
    return expression.IsThisProperty();
  }

  V8_INLINE static bool IsIdentifier(PreParserExpression expression) {
    return expression.IsIdentifier();
  }

  V8_INLINE static PreParserIdentifier AsIdentifier(
      PreParserExpression expression) {
    return expression.AsIdentifier();
  }

  V8_INLINE static PreParserExpression AsIdentifierExpression(
      PreParserExpression expression) {
    return expression;
  }

  V8_INLINE bool IsPrototype(PreParserIdentifier identifier) const {
    return identifier.IsPrototype();
  }

  V8_INLINE bool IsConstructor(PreParserIdentifier identifier) const {
    return identifier.IsConstructor();
  }

  V8_INLINE bool IsName(PreParserIdentifier identifier) const {
    return identifier.IsName();
  }

  V8_INLINE static bool IsBoilerplateProperty(PreParserExpression property) {
    // PreParser doesn't count boilerplate properties.
    return false;
  }

  V8_INLINE bool IsNative(PreParserExpression expr) const {
    // Preparsing is disabled for extensions (because the extension
    // details aren't passed to lazily compiled functions), so we
    // don't accept "native function" in the preparser and there is
    // no need to keep track of "native".
    return false;
  }

  V8_INLINE static bool IsArrayIndex(PreParserIdentifier string,
                                     uint32_t* index) {
    return false;
  }

  V8_INLINE bool IsUseStrictDirective(PreParserStatement statement) const {
    return statement.IsUseStrictLiteral();
  }

  V8_INLINE bool IsUseAsmDirective(PreParserStatement statement) const {
    return statement.IsUseAsmLiteral();
  }

  V8_INLINE bool IsStringLiteral(PreParserStatement statement) const {
    return statement.IsStringLiteral();
  }

  V8_INLINE static PreParserExpression GetPropertyValue(
      PreParserExpression property) {
    return PreParserExpression::Default();
  }

  V8_INLINE static void GetDefaultStrings(
      PreParserIdentifier* default_string,
      PreParserIdentifier* star_default_star_string) {}

  // Functions for encapsulating the differences between parsing and preparsing;
  // operations interleaved with the recursive descent.
  V8_INLINE static void PushLiteralName(PreParserIdentifier id) {}
  V8_INLINE static void PushVariableName(PreParserIdentifier id) {}
  V8_INLINE void PushPropertyName(PreParserExpression expression) {}
  V8_INLINE void PushEnclosingName(PreParserIdentifier name) {}
  V8_INLINE static void AddFunctionForNameInference(
      PreParserExpression expression) {}
  V8_INLINE static void InferFunctionName() {}

  V8_INLINE static void CheckAssigningFunctionLiteralToProperty(
      PreParserExpression left, PreParserExpression right) {}

  V8_INLINE void MarkExpressionAsAssigned(PreParserExpression expression) {
    // TODO(marja): To be able to produce the same errors, the preparser needs
    // to start tracking which expressions are variables and which are assigned.
    if (expression.variables_ != nullptr) {
      DCHECK(FLAG_lazy_inner_functions);
      DCHECK(track_unresolved_variables_);
      for (auto variable : *expression.variables_) {
        variable->set_is_assigned();
      }
    }
  }

  V8_INLINE bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
                                                        PreParserExpression y,
                                                        Token::Value op,
                                                        int pos) {
    return false;
  }

  V8_INLINE PreParserExpression BuildUnaryExpression(
      PreParserExpression expression, Token::Value op, int pos) {
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserStatement
  BuildInitializationBlock(DeclarationParsingResult* parsing_result,
                           ZoneList<const AstRawString*>* names, bool* ok) {
    for (auto declaration : parsing_result->declarations) {
      DeclareAndInitializeVariables(PreParserStatement::Default(),
                                    &(parsing_result->descriptor), &declaration,
                                    names, ok);
    }
    return PreParserStatement::Default();
  }

  V8_INLINE PreParserStatement InitializeForEachStatement(
      PreParserStatement stmt, PreParserExpression each,
      PreParserExpression subject, PreParserStatement body) {
    MarkExpressionAsAssigned(each);
    return stmt;
  }

  V8_INLINE PreParserStatement InitializeForOfStatement(
      PreParserStatement stmt, PreParserExpression each,
      PreParserExpression iterable, PreParserStatement body, bool finalize,
      IteratorType type, int next_result_pos = kNoSourcePosition) {
    MarkExpressionAsAssigned(each);
    return stmt;
  }

  V8_INLINE PreParserStatement RewriteForVarInLegacy(const ForInfo& for_info) {
    return PreParserStatement::Null();
  }

  V8_INLINE void DesugarBindingInForEachStatement(
      ForInfo* for_info, PreParserStatement* body_block,
      PreParserExpression* each_variable, bool* ok) {
    if (track_unresolved_variables_) {
      DCHECK(for_info->parsing_result.declarations.length() == 1);
      bool is_for_var_of =
          for_info->mode == ForEachStatement::ITERATE &&
          for_info->parsing_result.descriptor.mode == VariableMode::VAR;
      bool collect_names =
          IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
          is_for_var_of;

      DeclareAndInitializeVariables(
          PreParserStatement::Default(), &for_info->parsing_result.descriptor,
          &for_info->parsing_result.declarations[0],
          collect_names ? &for_info->bound_names : nullptr, ok);
    }
  }

  V8_INLINE PreParserStatement CreateForEachStatementTDZ(
      PreParserStatement init_block, const ForInfo& for_info, bool* ok) {
    if (track_unresolved_variables_) {
      if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
        for (auto name : for_info.bound_names) {
          scope()->DeclareVariableName(name, LET);
        }
        return PreParserStatement::Default();
      }
    }
    return init_block;
  }

  V8_INLINE StatementT DesugarLexicalBindingsInForStatement(
      PreParserStatement loop, PreParserStatement init,
      PreParserExpression cond, PreParserStatement next,
      PreParserStatement body, const SourceRange& body_range,
      Scope* inner_scope, const ForInfo& for_info, bool* ok) {
    // See Parser::DesugarLexicalBindingsInForStatement.
    if (track_unresolved_variables_) {
      for (auto name : for_info.bound_names) {
        inner_scope->DeclareVariableName(
            name, for_info.parsing_result.descriptor.mode);
      }
    }
    return loop;
  }

  V8_INLINE PreParserStatement BuildParameterInitializationBlock(
      const PreParserFormalParameters& parameters, bool* ok) {
    return PreParserStatement::Default();
  }

  V8_INLINE PreParserStatement
  BuildRejectPromiseOnException(PreParserStatement init_block) {
    return PreParserStatement::Default();
  }

  V8_INLINE void InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
    scope->HoistSloppyBlockFunctions(nullptr);
  }

  V8_INLINE void InsertShadowingVarBindingInitializers(
      PreParserStatement block) {}

  V8_INLINE PreParserExpression
  NewThrowReferenceError(MessageTemplate::Template message, int pos) {
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserExpression NewThrowSyntaxError(
      MessageTemplate::Template message, PreParserIdentifier arg, int pos) {
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserExpression NewThrowTypeError(
      MessageTemplate::Template message, PreParserIdentifier arg, int pos) {
    return PreParserExpression::Default();
  }

  // Reporting errors.
  V8_INLINE void ReportMessageAt(Scanner::Location source_location,
                                 MessageTemplate::Template message,
                                 const char* arg = NULL,
                                 ParseErrorType error_type = kSyntaxError) {
    pending_error_handler_->ReportMessageAt(source_location.beg_pos,
                                            source_location.end_pos, message,
                                            arg, error_type);
  }

  V8_INLINE void ReportMessageAt(Scanner::Location source_location,
                                 MessageTemplate::Template message,
                                 PreParserIdentifier arg,
                                 ParseErrorType error_type = kSyntaxError) {
    UNREACHABLE();
  }

  // "null" return type creators.
  V8_INLINE static PreParserIdentifier EmptyIdentifier() {
    return PreParserIdentifier::Empty();
  }
  V8_INLINE static bool IsEmptyIdentifier(PreParserIdentifier name) {
    return name.IsEmpty();
  }
  V8_INLINE static PreParserExpression EmptyExpression() {
    return PreParserExpression::Empty();
  }
  V8_INLINE static PreParserExpression EmptyLiteral() {
    return PreParserExpression::Default();
  }
  V8_INLINE static PreParserExpression EmptyObjectLiteralProperty() {
    return PreParserExpression::Default();
  }
  V8_INLINE static PreParserExpression EmptyClassLiteralProperty() {
    return PreParserExpression::Default();
  }
  V8_INLINE static PreParserExpression EmptyFunctionLiteral() {
    return PreParserExpression::Default();
  }

  V8_INLINE static bool IsEmptyExpression(PreParserExpression expr) {
    return expr.IsEmpty();
  }

  V8_INLINE static PreParserExpressionList NullExpressionList() {
    return PreParserExpressionList::Null();
  }

  V8_INLINE static bool IsNullExpressionList(PreParserExpressionList exprs) {
    return exprs.IsNull();
  }

  V8_INLINE static PreParserStatementList NullStatementList() {
    return PreParserStatementList::Null();
  }

  V8_INLINE static bool IsNullStatementList(PreParserStatementList stmts) {
    return stmts.IsNull();
  }

  V8_INLINE static PreParserStatement NullStatement() {
    return PreParserStatement::Null();
  }

  V8_INLINE bool IsNullStatement(PreParserStatement stmt) {
    return stmt.IsNullStatement();
  }

  V8_INLINE bool IsEmptyStatement(PreParserStatement stmt) {
    return stmt.IsEmptyStatement();
  }

  V8_INLINE static PreParserStatement NullBlock() {
    return PreParserStatement::Null();
  }

  V8_INLINE PreParserIdentifier EmptyIdentifierString() const {
    return PreParserIdentifier::Default();
  }

  // Odd-ball literal creators.
  V8_INLINE PreParserExpression GetLiteralTheHole(int position) {
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserExpression GetLiteralUndefined(int position) {
    return PreParserExpression::Default();
  }

  // Producing data during the recursive descent.
  PreParserIdentifier GetSymbol() const;

  V8_INLINE PreParserIdentifier GetNextSymbol() const {
    return PreParserIdentifier::Default();
  }

  V8_INLINE PreParserIdentifier GetNumberAsSymbol() const {
    return PreParserIdentifier::Default();
  }

  V8_INLINE PreParserExpression ThisExpression(int pos = kNoSourcePosition) {
    ZoneList<VariableProxy*>* variables = nullptr;
    if (track_unresolved_variables_) {
      VariableProxy* proxy = scope()->NewUnresolved(
          factory()->ast_node_factory(), ast_value_factory()->this_string(),
          pos, THIS_VARIABLE);

      variables = new (zone()) ZoneList<VariableProxy*>(1, zone());
      variables->Add(proxy, zone());
    }
    return PreParserExpression::This(variables);
  }

  V8_INLINE PreParserExpression NewSuperPropertyReference(int pos) {
    if (track_unresolved_variables_) {
      scope()->NewUnresolved(factory()->ast_node_factory(),
                             ast_value_factory()->this_function_string(), pos,
                             NORMAL_VARIABLE);
      scope()->NewUnresolved(factory()->ast_node_factory(),
                             ast_value_factory()->this_string(), pos,
                             THIS_VARIABLE);
    }
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserExpression NewSuperCallReference(int pos) {
    if (track_unresolved_variables_) {
      scope()->NewUnresolved(factory()->ast_node_factory(),
                             ast_value_factory()->this_function_string(), pos,
                             NORMAL_VARIABLE);
      scope()->NewUnresolved(factory()->ast_node_factory(),
                             ast_value_factory()->new_target_string(), pos,
                             NORMAL_VARIABLE);
      scope()->NewUnresolved(factory()->ast_node_factory(),
                             ast_value_factory()->this_string(), pos,
                             THIS_VARIABLE);
    }
    return PreParserExpression::SuperCallReference();
  }

  V8_INLINE PreParserExpression NewTargetExpression(int pos) {
    return PreParserExpression::NewTargetExpression();
  }

  V8_INLINE PreParserExpression FunctionSentExpression(int pos) {
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserExpression ExpressionFromLiteral(Token::Value token,
                                                      int pos) {
    return PreParserExpression::Default();
  }

  PreParserExpression ExpressionFromIdentifier(
      PreParserIdentifier name, int start_position,
      InferName infer = InferName::kYes);

  V8_INLINE PreParserExpression ExpressionFromString(int pos) {
    if (scanner()->IsUseStrict()) {
      return PreParserExpression::UseStrictStringLiteral();
    }
    return PreParserExpression::StringLiteral();
  }

  V8_INLINE PreParserExpressionList NewExpressionList(int size) const {
    return PreParserExpressionList();
  }

  V8_INLINE PreParserExpressionList NewObjectPropertyList(int size) const {
    return PreParserExpressionList();
  }

  V8_INLINE PreParserExpressionList NewClassPropertyList(int size) const {
    return PreParserExpressionList();
  }

  V8_INLINE PreParserStatementList NewStatementList(int size) const {
    return PreParserStatementList();
  }

  PreParserStatementList NewCaseClauseList(int size) {
    return PreParserStatementList();
  }

  V8_INLINE PreParserExpression
  NewV8Intrinsic(PreParserIdentifier name, PreParserExpressionList arguments,
                 int pos, bool* ok) {
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserStatement NewThrowStatement(PreParserExpression exception,
                                                 int pos) {
    return PreParserStatement::Jump();
  }

  V8_INLINE void AddParameterInitializationBlock(
      const PreParserFormalParameters& parameters, PreParserStatementList body,
      bool is_async, bool* ok) {}

  V8_INLINE void AddFormalParameter(PreParserFormalParameters* parameters,
                                    PreParserExpression pattern,
                                    PreParserExpression initializer,
                                    int initializer_end_position,
                                    bool is_rest) {
    if (track_unresolved_variables_) {
      DCHECK(FLAG_lazy_inner_functions);
      parameters->params.Add(new (zone()) PreParserFormalParameters::Parameter(
          pattern.variables_, is_rest));
    }
    parameters->UpdateArityAndFunctionLength(!initializer.IsEmpty(), is_rest);
  }

  V8_INLINE void DeclareFormalParameters(
      DeclarationScope* scope,
      const ThreadedList<PreParserFormalParameters::Parameter>& parameters,
      bool is_simple) {
    if (!is_simple) scope->SetHasNonSimpleParameters();
    if (track_unresolved_variables_) {
      DCHECK(FLAG_lazy_inner_functions);
      for (auto parameter : parameters) {
        DCHECK_IMPLIES(is_simple, parameter->variables_ != nullptr);
        DCHECK_IMPLIES(is_simple, parameter->variables_->length() == 1);
        // Make sure each parameter is added only once even if it's a
        // destructuring parameter which contains multiple names.
        bool add_parameter = true;
        if (parameter->variables_ != nullptr) {
          for (auto variable : (*parameter->variables_)) {
            // We declare the parameter name for all names, but only create a
            // parameter entry for the first one.
            scope->DeclareParameterName(variable->raw_name(),
                                        parameter->is_rest, ast_value_factory(),
                                        true, add_parameter);
            add_parameter = false;
          }
        }
        if (add_parameter) {
          // No names were declared; declare a dummy one here to up the
          // parameter count.
          DCHECK(!is_simple);
          scope->DeclareParameterName(ast_value_factory()->empty_string(),
                                      parameter->is_rest, ast_value_factory(),
                                      false, add_parameter);
        }
      }
    }
  }

  V8_INLINE void DeclareArrowFunctionFormalParameters(
      PreParserFormalParameters* parameters, PreParserExpression params,
      const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
      bool* ok) {
    // TODO(wingo): Detect duplicated identifiers in paramlists.  Detect
    // parameter lists that are too long.
    if (track_unresolved_variables_) {
      DCHECK(FLAG_lazy_inner_functions);
      if (params.variables_ != nullptr) {
        for (auto variable : *params.variables_) {
          parameters->scope->DeclareVariableName(variable->raw_name(), VAR);
        }
      }
    }
  }

  V8_INLINE PreParserExpression NoTemplateTag() {
    return PreParserExpression::NoTemplateTag();
  }

  V8_INLINE static bool IsTaggedTemplate(const PreParserExpression tag) {
    return !tag.IsNoTemplateTag();
  }

  V8_INLINE PreParserExpression
  ExpressionListToExpression(PreParserExpressionList args) {
    return PreParserExpression::Default(args.variables_);
  }

  V8_INLINE void SetFunctionNameFromPropertyName(
      PreParserExpression property, PreParserIdentifier name,
      const AstRawString* prefix = nullptr) {}
  V8_INLINE void SetFunctionNameFromIdentifierRef(
      PreParserExpression value, PreParserExpression identifier) {}

  V8_INLINE ZoneList<typename ExpressionClassifier::Error>*
  GetReportedErrorList() const {
    return function_state_->GetReportedErrorList();
  }

  V8_INLINE ZoneList<PreParserExpression>* GetNonPatternList() const {
    return function_state_->non_patterns_to_rewrite();
  }

  V8_INLINE void CountUsage(v8::Isolate::UseCounterFeature feature) {
    if (use_counts_ != nullptr) ++use_counts_[feature];
  }

  V8_INLINE bool ParsingDynamicFunctionDeclaration() const { return false; }

  V8_INLINE void RecordBlockSourceRange(PreParserStatement node,
                                        int32_t continuation_position) {}
  V8_INLINE void RecordCaseClauseSourceRange(PreParserStatement node,
                                             const SourceRange& body_range) {}
  V8_INLINE void RecordIfStatementSourceRange(PreParserStatement node,
                                              const SourceRange& then_range,
                                              const SourceRange& else_range) {}
  V8_INLINE void RecordJumpStatementSourceRange(PreParserStatement node,
                                                int32_t continuation_position) {
  }
  V8_INLINE void RecordIterationStatementSourceRange(
      PreParserStatement node, const SourceRange& body_range) {}
  V8_INLINE void RecordSwitchStatementSourceRange(
      PreParserStatement node, int32_t continuation_position) {}
  V8_INLINE void RecordThrowSourceRange(PreParserStatement node,
                                        int32_t continuation_position) {}
  V8_INLINE void RecordTryCatchStatementSourceRange(
      PreParserStatement node, const SourceRange& body_range) {}
  V8_INLINE void RecordTryFinallyStatementSourceRange(
      PreParserStatement node, const SourceRange& body_range) {}

  // Preparser's private field members.

  int* use_counts_;
  bool track_unresolved_variables_;
  PreParserLogger log_;
  PendingCompilationErrorHandler* pending_error_handler_;

  ProducedPreParsedScopeData* produced_preparsed_scope_data_;
};

PreParserExpression PreParser::SpreadCall(PreParserExpression function,
                                          PreParserExpressionList args, int pos,
                                          Call::PossiblyEval possibly_eval) {
  return factory()->NewCall(function, args, pos, possibly_eval);
}

PreParserExpression PreParser::SpreadCallNew(PreParserExpression function,
                                             PreParserExpressionList args,
                                             int pos) {
  return factory()->NewCallNew(function, args, pos);
}

PreParserExpression PreParser::CloseTemplateLiteral(TemplateLiteralState* state,
                                                    int start,
                                                    PreParserExpression tag) {
  return EmptyExpression();
}

}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_PREPARSER_H
