// 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-value-factory.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/pending-compilation-error-handler.h"
#include "src/parsing/preparser-logger.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 PreparseDataBuilder;

class PreParserIdentifier {
 public:
  PreParserIdentifier() : type_(kUnknownIdentifier) {}
  static PreParserIdentifier Default() {
    return PreParserIdentifier(kUnknownIdentifier);
  }
  static PreParserIdentifier Null() {
    return PreParserIdentifier(kNullIdentifier);
  }
  static PreParserIdentifier Eval() {
    return PreParserIdentifier(kEvalIdentifier);
  }
  static PreParserIdentifier Arguments() {
    return PreParserIdentifier(kArgumentsIdentifier);
  }
  static PreParserIdentifier Constructor() {
    return PreParserIdentifier(kConstructorIdentifier);
  }
  static PreParserIdentifier Await() {
    return PreParserIdentifier(kAwaitIdentifier);
  }
  static PreParserIdentifier Async() {
    return PreParserIdentifier(kAsyncIdentifier);
  }
  static PreParserIdentifier Name() {
    return PreParserIdentifier(kNameIdentifier);
  }
  static PreParserIdentifier PrivateName() {
    return PreParserIdentifier(kPrivateNameIdentifier);
  }
  bool IsNull() const { return type_ == kNullIdentifier; }
  bool IsEval() const { return type_ == kEvalIdentifier; }
  bool IsAsync() const { return type_ == kAsyncIdentifier; }
  bool IsArguments() const { return type_ == kArgumentsIdentifier; }
  bool IsEvalOrArguments() const {
    STATIC_ASSERT(kEvalIdentifier + 1 == kArgumentsIdentifier);
    return base::IsInRange(type_, kEvalIdentifier, kArgumentsIdentifier);
  }
  bool IsConstructor() const { return type_ == kConstructorIdentifier; }
  bool IsAwait() const { return type_ == kAwaitIdentifier; }
  bool IsName() const { return type_ == kNameIdentifier; }
  bool IsPrivateName() const { return type_ == kPrivateNameIdentifier; }

 private:
  enum Type : uint8_t {
    kNullIdentifier,
    kUnknownIdentifier,
    kEvalIdentifier,
    kArgumentsIdentifier,
    kConstructorIdentifier,
    kAwaitIdentifier,
    kAsyncIdentifier,
    kNameIdentifier,
    kPrivateNameIdentifier
  };

  explicit PreParserIdentifier(Type type) : string_(nullptr), type_(type) {}
  const AstRawString* string_;

  Type type_;
  friend class PreParserExpression;
  friend class PreParser;
  friend class PreParserFactory;
};

class PreParserExpression {
 public:
  PreParserExpression() : code_(TypeField::encode(kNull)) {}

  static PreParserExpression Null() { return PreParserExpression(); }
  static PreParserExpression Failure() {
    return PreParserExpression(TypeField::encode(kFailure));
  }

  static PreParserExpression Default() {
    return PreParserExpression(TypeField::encode(kExpression));
  }

  static PreParserExpression Spread(const PreParserExpression& expression) {
    return PreParserExpression(TypeField::encode(kSpreadExpression));
  }

  static PreParserExpression FromIdentifier(const PreParserIdentifier& id) {
    return PreParserExpression(TypeField::encode(kIdentifierExpression) |
                               IdentifierTypeField::encode(id.type_));
  }

  static PreParserExpression BinaryOperation(const PreParserExpression& left,
                                             Token::Value op,
                                             const PreParserExpression& right,
                                             Zone* zone) {
    return PreParserExpression(TypeField::encode(kExpression));
  }

  static PreParserExpression Assignment() {
    return PreParserExpression(TypeField::encode(kExpression) |
                               ExpressionTypeField::encode(kAssignment));
  }

  static PreParserExpression NewTargetExpression() {
    return PreParserExpression::Default();
  }

  static PreParserExpression ObjectLiteral() {
    return PreParserExpression(TypeField::encode(kObjectLiteralExpression));
  }

  static PreParserExpression ArrayLiteral() {
    return PreParserExpression(TypeField::encode(kArrayLiteralExpression));
  }

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

  static PreParserExpression This() {
    return PreParserExpression(TypeField::encode(kExpression) |
                               ExpressionTypeField::encode(kThisExpression));
  }

  static PreParserExpression ThisPrivateReference() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kThisPrivateReferenceExpression));
  }

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

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

  static PreParserExpression PrivateReference() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kPrivateReferenceExpression));
  }

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

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

  static PreParserExpression CallTaggedTemplate() {
    return PreParserExpression(
        TypeField::encode(kExpression) |
        ExpressionTypeField::encode(kCallTaggedTemplateExpression));
  }

  bool is_tagged_template() const {
    DCHECK(IsCall());
    return ExpressionTypeField::decode(code_) == kCallTaggedTemplateExpression;
  }

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

  bool IsNull() const { return TypeField::decode(code_) == kNull; }
  bool IsFailureExpression() const {
    return TypeField::decode(code_) == kFailure;
  }

  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 IsPattern() const {
    STATIC_ASSERT(kObjectLiteralExpression + 1 == kArrayLiteralExpression);
    return base::IsInRange(TypeField::decode(code_), kObjectLiteralExpression,
                           kArrayLiteralExpression);
  }

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

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

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

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

  bool IsPrivateReference() const {
    return TypeField::decode(code_) == kExpression &&
           (ExpressionTypeField::decode(code_) == kPrivateReferenceExpression ||
            ExpressionTypeField::decode(code_) ==
                kThisPrivateReferenceExpression);
  }

  bool IsCall() const {
    return TypeField::decode(code_) == kExpression &&
           (ExpressionTypeField::decode(code_) == kCallExpression ||
            ExpressionTypeField::decode(code_) == kCallEvalExpression ||
            ExpressionTypeField::decode(code_) ==
                kCallTaggedTemplateExpression);
  }
  PreParserExpression* AsCall() {
    if (IsCall()) return this;
    return nullptr;
  }

  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 IsSpread() const {
    return TypeField::decode(code_) == kSpreadExpression;
  }

  bool is_parenthesized() const { return IsParenthesizedField::decode(code_); }

  void mark_parenthesized() {
    code_ = IsParenthesizedField::update(code_, true);
  }

  void clear_parenthesized() {
    code_ = IsParenthesizedField::update(code_, false);
  }

  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 mark_as_oneshot_iife() {}

  int position() const { return kNoSourcePosition; }
  void set_function_token_position(int position) {}
  void set_scope(Scope* scope) {}
  void set_suspend_count(int suspend_count) {}

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

  enum ExpressionType {
    kThisExpression,
    kThisPropertyExpression,
    kThisPrivateReferenceExpression,
    kPropertyExpression,
    kPrivateReferenceExpression,
    kCallExpression,
    kCallEvalExpression,
    kCallTaggedTemplateExpression,
    kSuperCallReference,
    kAssignment
  };

  explicit PreParserExpression(uint32_t expression_code)
      : code_(expression_code) {}

  // The first three bits are for the Type.
  using TypeField = base::BitField<Type, 0, 3>;

  // 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.
  using IsParenthesizedField = TypeField::Next<bool, 1>;

  // The rest of the bits are interpreted depending on the value
  // of the Type field, so they can share the storage.
  using ExpressionTypeField = IsParenthesizedField::Next<ExpressionType, 4>;
  using IdentifierTypeField =
      IsParenthesizedField::Next<PreParserIdentifier::Type, 8>;
  using HasCoverInitializedNameField = IsParenthesizedField::Next<bool, 1>;

  uint32_t code_;
  friend class PreParser;
  friend class PreParserFactory;
  friend class PreParserExpressionList;
};

class PreParserStatement;
class PreParserStatementList {
 public:
  PreParserStatementList() : PreParserStatementList(false) {}
  PreParserStatementList* operator->() { return this; }
  void Add(const PreParserStatement& element, Zone* zone) {}
  static PreParserStatementList Null() { return PreParserStatementList(true); }
  bool IsNull() const { return is_null_; }

 private:
  explicit PreParserStatementList(bool is_null) : is_null_(is_null) {}
  bool is_null_;
};

class PreParserScopedStatementList {
 public:
  explicit PreParserScopedStatementList(std::vector<void*>* buffer) {}
  void Rewind() {}
  void MergeInto(const PreParserScopedStatementList* other) {}
  void Add(const PreParserStatement& element) {}
  int length() { return 0; }
};

// 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.
class PreParserExpressionList {
 public:
  explicit PreParserExpressionList(std::vector<void*>* buffer) : length_(0) {}

  int length() const { return length_; }

  void Add(const PreParserExpression& expression) {
    ++length_;
  }

 private:
  int length_;

  friend class PreParser;
  friend class PreParserFactory;
};

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

  static PreParserStatement Iteration() {
    return PreParserStatement(kIterationStatement);
  }

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

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

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

  void InitializeStatements(const PreParserScopedStatementList& statements,
                            Zone* zone) {}

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

  bool IsStringLiteral() { return code_ == kStringLiteralExpressionStatement; }

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

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

  bool IsIterationStatement() { return code_ == kIterationStatement; }

  bool IsEmptyStatement() {
    DCHECK(!IsNull());
    return code_ == kEmptyStatement;
  }

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

  PreParserStatementList statements() { return PreParserStatementList(); }
  PreParserStatementList cases() { return PreParserStatementList(); }

  void set_scope(Scope* scope) {}
  void Initialize(const PreParserExpression& cond, PreParserStatement body,
                  const SourceRange& body_range = {}) {}
  void Initialize(PreParserStatement init, const PreParserExpression& cond,
                  PreParserStatement next, PreParserStatement body,
                  const SourceRange& body_range = {}) {}
  void Initialize(PreParserExpression each, const PreParserExpression& subject,
                  PreParserStatement body, const SourceRange& body_range = {}) {
  }

 protected:
  enum Type {
    kNullStatement,
    kEmptyStatement,
    kUnknownStatement,
    kJumpStatement,
    kIterationStatement,
    kStringLiteralExpressionStatement,
  };

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

 private:
  Type code_;
};

// A PreParserBlock extends statement with a place to store the scope.
// The scope is dropped as the block is returned as a statement.
class PreParserBlock : public PreParserStatement {
 public:
  void set_scope(Scope* scope) { scope_ = scope; }
  Scope* scope() const { return scope_; }
  static PreParserBlock Default() {
    return PreParserBlock(PreParserStatement::kUnknownStatement);
  }
  static PreParserBlock Null() {
    return PreParserBlock(PreParserStatement::kNullStatement);
  }
  // Dummy implementation for making block->somefunc() work in both Parser and
  // PreParser.
  PreParserBlock* operator->() { return this; }

 private:
  explicit PreParserBlock(PreParserStatement::Type type)
      : PreParserStatement(type), scope_(nullptr) {}
  Scope* scope_;
};

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

  AstNodeFactory* ast_node_factory() { return &ast_node_factory_; }

  PreParserExpression NewStringLiteral(const PreParserIdentifier& identifier,
                                       int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewNumberLiteral(double number,
                                       int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewUndefinedLiteral(int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewTheHoleLiteral() {
    return PreParserExpression::Default();
  }
  PreParserExpression NewRegExpLiteral(const PreParserIdentifier& js_pattern,
                                       int js_flags, int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewArrayLiteral(const PreParserExpressionList& values,
                                      int first_spread_index, int pos) {
    return PreParserExpression::ArrayLiteral();
  }
  PreParserExpression NewClassLiteralProperty(const PreParserExpression& key,
                                              const PreParserExpression& value,
                                              ClassLiteralProperty::Kind kind,
                                              bool is_static,
                                              bool is_computed_name,
                                              bool is_private) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewObjectLiteralProperty(const PreParserExpression& key,
                                               const PreParserExpression& value,
                                               ObjectLiteralProperty::Kind kind,
                                               bool is_computed_name) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewObjectLiteralProperty(const PreParserExpression& key,
                                               const PreParserExpression& value,
                                               bool is_computed_name) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewObjectLiteral(
      const PreParserExpressionList& properties, int boilerplate_properties,
      int pos, bool has_rest_property) {
    return PreParserExpression::ObjectLiteral();
  }
  PreParserExpression NewVariableProxy(void* variable) {
    return PreParserExpression::Default();
  }

  PreParserExpression NewOptionalChain(const PreParserExpression& expr) {
    // Needed to track `delete a?.#b` early errors
    if (expr.IsPrivateReference()) {
      return PreParserExpression::PrivateReference();
    }
    return PreParserExpression::Default();
  }

  PreParserExpression NewProperty(const PreParserExpression& obj,
                                  const PreParserExpression& key, int pos,
                                  bool optional_chain = false) {
    if (key.IsIdentifier() && key.AsIdentifier().IsPrivateName()) {
      if (obj.IsThis()) {
        return PreParserExpression::ThisPrivateReference();
      }
      return PreParserExpression::PrivateReference();
    }

    if (obj.IsThis()) {
      return PreParserExpression::ThisProperty();
    }
    return PreParserExpression::Property();
  }
  PreParserExpression NewUnaryOperation(Token::Value op,
                                        const PreParserExpression& expression,
                                        int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewBinaryOperation(Token::Value op,
                                         const PreParserExpression& left,
                                         const PreParserExpression& right,
                                         int pos) {
    return PreParserExpression::BinaryOperation(left, op, right, zone_);
  }
  PreParserExpression NewCompareOperation(Token::Value op,
                                          const PreParserExpression& left,
                                          const PreParserExpression& right,
                                          int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewAssignment(Token::Value op,
                                    const PreParserExpression& left,
                                    const 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();
  }
  PreParserExpression NewYield(const PreParserExpression& expression, int pos,
                               Suspend::OnAbruptResume on_abrupt_resume) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewAwait(const PreParserExpression& expression, int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewYieldStar(const PreParserExpression& iterable,
                                   int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewConditional(const PreParserExpression& condition,
                                     const PreParserExpression& then_expression,
                                     const PreParserExpression& else_expression,
                                     int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewCountOperation(Token::Value op, bool is_prefix,
                                        const PreParserExpression& expression,
                                        int pos) {
    return PreParserExpression::Default();
  }
  PreParserExpression NewCall(PreParserExpression expression,
                              const PreParserExpressionList& arguments, int pos,
                              Call::PossiblyEval possibly_eval = Call::NOT_EVAL,
                              bool optional_chain = false) {
    if (possibly_eval == Call::IS_POSSIBLY_EVAL) {
      DCHECK(expression.IsIdentifier() && expression.AsIdentifier().IsEval());
      DCHECK(!optional_chain);
      return PreParserExpression::CallEval();
    }
    return PreParserExpression::Call();
  }
  PreParserExpression NewTaggedTemplate(
      PreParserExpression expression, const PreParserExpressionList& arguments,
      int pos) {
    return PreParserExpression::CallTaggedTemplate();
  }
  PreParserExpression NewCallNew(const PreParserExpression& expression,
                                 const PreParserExpressionList& arguments,
                                 int pos) {
    return PreParserExpression::Default();
  }
  PreParserStatement NewReturnStatement(
      const PreParserExpression& expression, int pos,
      int continuation_pos = kNoSourcePosition) {
    return PreParserStatement::Jump();
  }
  PreParserStatement NewAsyncReturnStatement(
      const PreParserExpression& expression, int pos,
      int continuation_pos = kNoSourcePosition) {
    return PreParserStatement::Jump();
  }
  PreParserExpression NewFunctionLiteral(
      const PreParserIdentifier& name, Scope* scope,
      const PreParserScopedStatementList& body, int expected_property_count,
      int parameter_count, int function_length,
      FunctionLiteral::ParameterFlag has_duplicate_parameters,
      FunctionSyntaxKind function_syntax_kind,
      FunctionLiteral::EagerCompileHint eager_compile_hint, int position,
      bool has_braces, int function_literal_id,
      ProducedPreparseData* produced_preparse_data = nullptr) {
    DCHECK_NULL(produced_preparse_data);
    return PreParserExpression::Default();
  }

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

  PreParserExpression NewEmptyParentheses(int pos) {
    PreParserExpression result = PreParserExpression::Default();
    result.mark_parenthesized();
    return result;
  }

  PreParserStatement EmptyStatement() { return PreParserStatement::Default(); }

  PreParserBlock NewBlock(int capacity, bool ignore_completion_value) {
    return PreParserBlock::Default();
  }

  PreParserBlock NewBlock(bool ignore_completion_value, bool is_breakable) {
    return PreParserBlock::Default();
  }

  PreParserBlock NewBlock(bool ignore_completion_value,
                          const PreParserScopedStatementList& list) {
    return PreParserBlock::Default();
  }

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

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

  PreParserStatement NewIfStatement(const 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,
                                      const PreParserExpression& expression,
                                      PreParserStatement statement, int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewDoWhileStatement(int pos) {
    return PreParserStatement::Iteration();
  }

  PreParserStatement NewWhileStatement(int pos) {
    return PreParserStatement::Iteration();
  }

  PreParserStatement NewSwitchStatement(const PreParserExpression& tag,
                                        int pos) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewCaseClause(
      const PreParserExpression& label,
      const PreParserScopedStatementList& statements) {
    return PreParserStatement::Default();
  }

  PreParserStatement NewForStatement(int pos) {
    return PreParserStatement::Iteration();
  }

  PreParserStatement NewForEachStatement(ForEachStatement::VisitMode visit_mode,
                                         int pos) {
    return PreParserStatement::Iteration();
  }

  PreParserStatement NewForOfStatement(int pos, IteratorType type) {
    return PreParserStatement::Iteration();
  }

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

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

 private:
  // For creating VariableProxy objects to track unresolved variables.
  AstNodeFactory ast_node_factory_;
  Zone* zone_;
};

class PreParser;

class PreParserFormalParameters : public FormalParametersBase {
 public:
  explicit PreParserFormalParameters(DeclarationScope* scope)
      : FormalParametersBase(scope) {}

  void set_has_duplicate() { has_duplicate_ = true; }
  bool has_duplicate() { return has_duplicate_; }
  void ValidateDuplicate(PreParser* preparser) const;

  void set_strict_parameter_error(const Scanner::Location& loc,
                                  MessageTemplate message) {
    strict_parameter_error_ = loc.IsValid();
  }
  void ValidateStrictMode(PreParser* preparser) const;

 private:
  bool has_duplicate_ = false;
  bool strict_parameter_error_ = false;
};

class PreParserFuncNameInferrer {
 public:
  explicit PreParserFuncNameInferrer(AstValueFactory* avf) {}
  void RemoveAsyncKeywordFromEnd() const {}
  void Infer() const {}
  void RemoveLastFunction() const {}

  class State {
   public:
    explicit State(PreParserFuncNameInferrer* fni) {}

   private:
    DISALLOW_COPY_AND_ASSIGN(State);
  };

 private:
  DISALLOW_COPY_AND_ASSIGN(PreParserFuncNameInferrer);
};

class PreParserSourceRange {
 public:
  PreParserSourceRange() = default;
  PreParserSourceRange(int start, int end) {}
  static PreParserSourceRange Empty() { return PreParserSourceRange(); }
  static PreParserSourceRange OpenEnded(int32_t start) { return Empty(); }
  static const PreParserSourceRange& ContinuationOf(
      const PreParserSourceRange& that, int end) {
    return that;
  }
};

class PreParserSourceRangeScope {
 public:
  PreParserSourceRangeScope(Scanner* scanner, PreParserSourceRange* range) {}
  const PreParserSourceRange& Finalize() const { return range_; }

 private:
  PreParserSourceRange range_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(PreParserSourceRangeScope);
};

class PreParserPropertyList {};

template <>
struct ParserTypes<PreParser> {
  using Base = ParserBase<PreParser>;
  using Impl = PreParser;

  // Return types for traversing functions.
  using ClassLiteralProperty = PreParserExpression;
  using Expression = PreParserExpression;
  using FunctionLiteral = PreParserExpression;
  using ObjectLiteralProperty = PreParserExpression;
  using Suspend = PreParserExpression;
  using ExpressionList = PreParserExpressionList;
  using ObjectPropertyList = PreParserExpressionList;
  using FormalParameters = PreParserFormalParameters;
  using Identifier = PreParserIdentifier;
  using ClassPropertyList = PreParserPropertyList;
  using StatementList = PreParserScopedStatementList;
  using Block = PreParserBlock;
  using BreakableStatement = PreParserStatement;
  using ForStatement = PreParserStatement;
  using IterationStatement = PreParserStatement;
  using Statement = PreParserStatement;

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

  // Other implementation-specific tasks.
  using FuncNameInferrer = PreParserFuncNameInferrer;
  using SourceRange = PreParserSourceRange;
  using SourceRangeScope = PreParserSourceRangeScope;
};


// 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>;

 public:
  using Identifier = PreParserIdentifier;
  using Expression = PreParserExpression;
  using Statement = PreParserStatement;

  enum PreParseResult {
    kPreParseStackOverflow,
    kPreParseNotIdentifiableError,
    kPreParseSuccess
  };

  PreParser(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
            AstValueFactory* ast_value_factory,
            PendingCompilationErrorHandler* pending_error_handler,
            RuntimeCallStats* runtime_call_stats, Logger* logger,
            UnoptimizedCompileFlags flags, bool parsing_on_main_thread = true)
      : ParserBase<PreParser>(zone, scanner, stack_limit, nullptr,
                              ast_value_factory, pending_error_handler,
                              runtime_call_stats, logger, flags,
                              parsing_on_main_thread),
        use_counts_(nullptr),
        preparse_data_builder_(nullptr),
        preparse_data_builder_buffer_() {
    preparse_data_builder_buffer_.reserve(16);
  }

  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.
  V8_EXPORT_PRIVATE PreParseResult PreParseProgram();

  // 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,
      FunctionSyntaxKind function_syntax_kind, DeclarationScope* function_scope,
      int* use_counts, ProducedPreparseData** produced_preparser_scope_data);

  PreparseDataBuilder* preparse_data_builder() const {
    return preparse_data_builder_;
  }

  void set_preparse_data_builder(PreparseDataBuilder* preparse_data_builder) {
    preparse_data_builder_ = preparse_data_builder;
  }

  std::vector<void*>* preparse_data_builder_buffer() {
    return &preparse_data_builder_buffer_;
  }

 private:
  friend class i::ExpressionScope<ParserTypes<PreParser>>;
  friend class i::VariableDeclarationParsingScope<ParserTypes<PreParser>>;
  friend class i::ParameterDeclarationParsingScope<ParserTypes<PreParser>>;
  friend class i::ArrowHeadParsingScope<ParserTypes<PreParser>>;
  friend class PreParserFormalParameters;
  // 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; }

  PendingCompilationErrorHandler* pending_error_handler() {
    return pending_error_handler_;
  }

  V8_INLINE bool SkipFunction(const AstRawString* name, FunctionKind kind,
                              FunctionSyntaxKind function_syntax_kind,
                              DeclarationScope* function_scope,
                              int* num_parameters, int* function_length,
                              ProducedPreparseData** produced_preparse_data) {
    UNREACHABLE();
  }

  Expression ParseFunctionLiteral(
      Identifier name, Scanner::Location function_name_location,
      FunctionNameValidity function_name_validity, FunctionKind kind,
      int function_token_pos, FunctionSyntaxKind function_syntax_kind,
      LanguageMode language_mode,
      ZonePtrList<const AstRawString>* arguments_for_wrapped_function);

  PreParserExpression InitializeObjectLiteral(PreParserExpression literal) {
    return literal;
  }

  bool HasCheckedSyntax() { return false; }

  void ParseStatementListAndLogFunction(PreParserFormalParameters* formals);

  struct TemplateLiteralState {};

  V8_INLINE TemplateLiteralState OpenTemplateLiteral(int pos) {
    return TemplateLiteralState();
  }
  V8_INLINE void AddTemplateExpression(TemplateLiteralState* state,
                                       const PreParserExpression& expression) {}
  V8_INLINE void AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
                                 bool tail) {}
  V8_INLINE PreParserExpression CloseTemplateLiteral(
      TemplateLiteralState* state, int start, const PreParserExpression& tag) {
    return PreParserExpression::Default();
  }
  V8_INLINE bool IsPrivateReference(const PreParserExpression& expression) {
    return expression.IsPrivateReference();
  }
  V8_INLINE void SetLanguageMode(Scope* scope, LanguageMode mode) {
    scope->SetLanguageMode(mode);
  }
  V8_INLINE void SetAsmModule() {}

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

  V8_INLINE void PrepareGeneratorVariables() {}
  V8_INLINE void RewriteAsyncFunctionBody(
      const PreParserScopedStatementList* body, PreParserStatement block,
      const PreParserExpression& return_value) {}

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

  Variable* DeclareVariable(const AstRawString* name, VariableKind kind,
                            VariableMode mode, InitializationFlag init,
                            Scope* scope, bool* was_added, int position) {
    return DeclareVariableName(name, mode, scope, was_added, position, kind);
  }

  void DeclareAndBindVariable(const VariableProxy* proxy, VariableKind kind,
                              VariableMode mode, Scope* scope, bool* was_added,
                              int initializer_position) {
    Variable* var = DeclareVariableName(proxy->raw_name(), mode, scope,
                                        was_added, proxy->position(), kind);
    var->set_initializer_position(initializer_position);
    // Don't bother actually binding the proxy.
  }

  Variable* DeclarePrivateVariableName(const AstRawString* name,
                                       ClassScope* scope, VariableMode mode,
                                       IsStaticFlag is_static_flag,
                                       bool* was_added) {
    DCHECK(IsConstVariableMode(mode));
    return scope->DeclarePrivateName(name, mode, is_static_flag, was_added);
  }

  Variable* DeclareVariableName(const AstRawString* name, VariableMode mode,
                                Scope* scope, bool* was_added,
                                int position = kNoSourcePosition,
                                VariableKind kind = NORMAL_VARIABLE) {
    DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode));
    Variable* var = scope->DeclareVariableName(name, mode, was_added, kind);
    if (var == nullptr) {
      ReportUnidentifiableError();
      if (!IsLexicalVariableMode(mode)) scope = scope->GetDeclarationScope();
      var = scope->LookupLocal(name);
    } else if (var->scope() != scope) {
      DCHECK_NE(kNoSourcePosition, position);
      DCHECK_EQ(VariableMode::kVar, mode);
      Declaration* nested_declaration =
          factory()->ast_node_factory()->NewNestedVariableDeclaration(scope,
                                                                      position);
      nested_declaration->set_var(var);
      var->scope()->declarations()->Add(nested_declaration);
    }
    return var;
  }

  V8_INLINE PreParserBlock RewriteCatchPattern(CatchInfo* catch_info) {
    return PreParserBlock::Default();
  }

  V8_INLINE void ReportVarRedeclarationIn(const AstRawString* name,
                                          Scope* scope) {
    ReportUnidentifiableError();
  }

  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 ReportUnexpectedTokenAt(
      Scanner::Location location, Token::Value token,
      MessageTemplate message = MessageTemplate::kUnexpectedToken) {
    ReportUnidentifiableError();
  }
  V8_INLINE void ParseAndRewriteGeneratorFunctionBody(
      int pos, FunctionKind kind, PreParserScopedStatementList* body) {
    ParseStatementList(body, Token::RBRACE);
  }
  V8_INLINE void ParseAndRewriteAsyncGeneratorFunctionBody(
      int pos, FunctionKind kind, PreParserScopedStatementList* body) {
    ParseStatementList(body, Token::RBRACE);
  }
  V8_INLINE void DeclareFunctionNameVar(const AstRawString* function_name,
                                        FunctionSyntaxKind function_syntax_kind,
                                        DeclarationScope* function_scope) {
    if (function_syntax_kind == FunctionSyntaxKind::kNamedExpression &&
        function_scope->LookupLocal(function_name) == nullptr) {
      DCHECK_EQ(function_scope, scope());
      function_scope->DeclareFunctionVar(function_name);
    }
  }

  V8_INLINE void DeclareFunctionNameVar(
      const PreParserIdentifier& function_name,
      FunctionSyntaxKind function_syntax_kind,
      DeclarationScope* function_scope) {
    DeclareFunctionNameVar(function_name.string_, function_syntax_kind,
                           function_scope);
  }

  bool IdentifierEquals(const PreParserIdentifier& identifier,
                        const AstRawString* other);

  V8_INLINE PreParserStatement DeclareFunction(
      const PreParserIdentifier& variable_name,
      const PreParserExpression& function, VariableMode mode, VariableKind kind,
      int beg_pos, int end_pos, ZonePtrList<const AstRawString>* names) {
    DCHECK_NULL(names);
    bool was_added;
    Variable* var = DeclareVariableName(variable_name.string_, mode, scope(),
                                        &was_added, beg_pos, kind);
    if (kind == SLOPPY_BLOCK_FUNCTION_VARIABLE) {
      Token::Value init =
          loop_nesting_depth() > 0 ? Token::ASSIGN : Token::INIT;
      SloppyBlockFunctionStatement* statement =
          factory()->ast_node_factory()->NewSloppyBlockFunctionStatement(
              end_pos, var, init);
      GetDeclarationScope()->DeclareSloppyBlockFunction(statement);
    }
    return Statement::Default();
  }

  V8_INLINE PreParserStatement DeclareClass(
      const PreParserIdentifier& variable_name,
      const PreParserExpression& value, ZonePtrList<const AstRawString>* names,
      int class_token_pos, int end_pos) {
    // Preparser shouldn't be used in contexts where we need to track the names.
    DCHECK_NULL(names);
    bool was_added;
    DeclareVariableName(variable_name.string_, VariableMode::kLet, scope(),
                        &was_added);
    return PreParserStatement::Default();
  }
  V8_INLINE void DeclareClassVariable(ClassScope* scope,
                                      const PreParserIdentifier& name,
                                      ClassInfo* class_info,
                                      int class_token_pos) {
    DCHECK_IMPLIES(IsNull(name), class_info->is_anonymous);
    // Declare a special class variable for anonymous classes with the dot
    // if we need to save it for static private method access.
    scope->DeclareClassVariable(ast_value_factory(), name.string_,
                                class_token_pos);
  }
  V8_INLINE void DeclarePublicClassMethod(const PreParserIdentifier& class_name,
                                          const PreParserExpression& property,
                                          bool is_constructor,
                                          ClassInfo* class_info) {}
  V8_INLINE void DeclarePublicClassField(ClassScope* scope,
                                         const PreParserExpression& property,
                                         bool is_static, bool is_computed_name,
                                         ClassInfo* class_info) {
    if (is_computed_name) {
      bool was_added;
      DeclareVariableName(
          ClassFieldVariableName(ast_value_factory(),
                                 class_info->computed_field_count),
          VariableMode::kConst, scope, &was_added);
    }
  }

  V8_INLINE void DeclarePrivateClassMember(
      ClassScope* scope, const PreParserIdentifier& property_name,
      const PreParserExpression& property, ClassLiteralProperty::Kind kind,
      bool is_static, ClassInfo* class_info) {
    bool was_added;

    DeclarePrivateVariableName(
        property_name.string_, scope, GetVariableMode(kind),
        is_static ? IsStaticFlag::kStatic : IsStaticFlag::kNotStatic,
        &was_added);
    if (!was_added) {
      Scanner::Location loc(property.position(), property.position() + 1);
      ReportMessageAt(loc, MessageTemplate::kVarRedeclaration,
                      property_name.string_);
    }
  }

  V8_INLINE PreParserExpression
  RewriteClassLiteral(ClassScope* scope, const PreParserIdentifier& name,
                      ClassInfo* class_info, int pos, int end_pos) {
    bool has_default_constructor = !class_info->has_seen_constructor;
    // Account for the default constructor.
    if (has_default_constructor) {
      // Creating and disposing of a FunctionState makes tracking of
      // next_function_is_likely_called match what Parser does. TODO(marja):
      // Make the lazy function + next_function_is_likely_called + default ctor
      // logic less surprising. Default ctors shouldn't affect the laziness of
      // functions.
      bool has_extends = class_info->extends.IsNull();
      FunctionKind kind = has_extends ? FunctionKind::kDefaultDerivedConstructor
                                      : FunctionKind::kDefaultBaseConstructor;
      DeclarationScope* function_scope = NewFunctionScope(kind);
      SetLanguageMode(function_scope, LanguageMode::kStrict);
      function_scope->set_start_position(pos);
      function_scope->set_end_position(pos);
      FunctionState function_state(&function_state_, &scope_, function_scope);
      GetNextFunctionLiteralId();
    }
    if (class_info->has_static_class_fields) {
      GetNextFunctionLiteralId();
    }
    if (class_info->has_instance_members) {
      GetNextFunctionLiteralId();
    }
    return PreParserExpression::Default();
  }

  V8_INLINE PreParserStatement DeclareNative(const PreParserIdentifier& name,
                                             int pos) {
    return PreParserStatement::Default();
  }

  V8_INLINE void QueueDestructuringAssignmentForRewriting(
      PreParserExpression assignment) {}

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

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

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

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

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

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

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

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

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

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

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

  V8_INLINE bool IsNative(const 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(const PreParserIdentifier& string,
                                     uint32_t* index) {
    return false;
  }

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

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

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

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

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

  V8_INLINE NaryOperation* CollapseNaryExpression(PreParserExpression* x,
                                                  PreParserExpression y,
                                                  Token::Value op, int pos,
                                                  const SourceRange& range) {
    x->clear_parenthesized();
    return nullptr;
  }

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

  V8_INLINE PreParserStatement
  BuildInitializationBlock(DeclarationParsingResult* parsing_result) {
    return PreParserStatement::Default();
  }

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

  V8_INLINE void DesugarBindingInForEachStatement(
      ForInfo* for_info, PreParserStatement* body_block,
      PreParserExpression* each_variable) {
  }

  V8_INLINE PreParserBlock CreateForEachStatementTDZ(PreParserBlock init_block,
                                                     const ForInfo& for_info) {
    if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
      for (auto name : for_info.bound_names) {
        bool was_added;
        DeclareVariableName(name, VariableMode::kLet, scope(), &was_added);
      }
      return PreParserBlock::Default();
    }
    return init_block;
  }

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

  PreParserBlock BuildParameterInitializationBlock(
      const PreParserFormalParameters& parameters);

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

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

  V8_INLINE void InsertShadowingVarBindingInitializers(
      PreParserStatement block) {}

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

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

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

  // Reporting errors.
  void ReportMessageAt(Scanner::Location source_location,
                       MessageTemplate message, const char* arg = nullptr) {
    pending_error_handler()->ReportMessageAt(
        source_location.beg_pos, source_location.end_pos, message, arg);
    scanner()->set_parser_error();
  }

  V8_INLINE void ReportUnidentifiableError() {
    pending_error_handler()->set_unidentifiable_error();
    scanner()->set_parser_error();
  }

  V8_INLINE void ReportMessageAt(Scanner::Location source_location,
                                 MessageTemplate message,
                                 const PreParserIdentifier& arg) {
    ReportMessageAt(source_location, message, arg.string_);
  }

  void ReportMessageAt(Scanner::Location source_location,
                       MessageTemplate message, const AstRawString* arg) {
    pending_error_handler()->ReportMessageAt(
        source_location.beg_pos, source_location.end_pos, message, arg);
    scanner()->set_parser_error();
  }

  const AstRawString* GetRawNameFromIdentifier(const PreParserIdentifier& arg) {
    return arg.string_;
  }

  PreParserStatement AsIterationStatement(PreParserStatement s) { return s; }

  // "null" return type creators.
  V8_INLINE static PreParserIdentifier NullIdentifier() {
    return PreParserIdentifier::Null();
  }
  V8_INLINE static PreParserExpression NullExpression() {
    return PreParserExpression::Null();
  }
  V8_INLINE static PreParserExpression FailureExpression() {
    return PreParserExpression::Failure();
  }
  V8_INLINE static PreParserExpression NullLiteralProperty() {
    return PreParserExpression::Null();
  }
  V8_INLINE static PreParserStatementList NullStatementList() {
    return PreParserStatementList::Null();
  }
  V8_INLINE static PreParserStatement NullStatement() {
    return PreParserStatement::Null();
  }
  V8_INLINE static PreParserBlock NullBlock() { return PreParserBlock::Null(); }

  template <typename T>
  V8_INLINE static bool IsNull(T subject) {
    return subject.IsNull();
  }

  V8_INLINE static bool IsIterationStatement(PreParserStatement subject) {
    return subject.IsIterationStatement();
  }

  V8_INLINE PreParserIdentifier EmptyIdentifierString() const {
    PreParserIdentifier result = PreParserIdentifier::Default();
    result.string_ = ast_value_factory()->empty_string();
    return result;
  }

  // Producing data during the recursive descent.
  PreParserIdentifier GetSymbol() const {
    return PreParserIdentifier::Default();
  }

  PreParserIdentifier GetIdentifier() const;

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

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

  V8_INLINE PreParserExpression ThisExpression() {
    UseThis();
    return PreParserExpression::This();
  }

  V8_INLINE PreParserExpression NewThisExpression(int pos) {
    UseThis();
    return PreParserExpression::This();
  }

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

  V8_INLINE PreParserExpression NewSuperCallReference(int pos) {
    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);
    return PreParserExpression::SuperCallReference();
  }

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

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

  V8_INLINE PreParserExpression ExpressionFromLiteral(Token::Value token,
                                                      int pos) {
    if (token != Token::STRING) return PreParserExpression::Default();
    return PreParserExpression::StringLiteral();
  }

  PreParserExpression ExpressionFromPrivateName(
      PrivateNameScopeIterator* private_name_scope,
      const PreParserIdentifier& name, int start_position) {
    VariableProxy* proxy = factory()->ast_node_factory()->NewVariableProxy(
        name.string_, NORMAL_VARIABLE, start_position);
    private_name_scope->AddUnresolvedPrivateName(proxy);
    return PreParserExpression::FromIdentifier(name);
  }

  PreParserExpression ExpressionFromIdentifier(
      const PreParserIdentifier& name, int start_position,
      InferName infer = InferName::kYes) {
    expression_scope()->NewVariable(name.string_, start_position);
    return PreParserExpression::FromIdentifier(name);
  }

  V8_INLINE void DeclareIdentifier(const PreParserIdentifier& name,
                                   int start_position) {
    expression_scope()->Declare(name.string_, start_position);
  }

  V8_INLINE Variable* DeclareCatchVariableName(
      Scope* scope, const PreParserIdentifier& identifier) {
    return scope->DeclareCatchVariableName(identifier.string_);
  }

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

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

  V8_INLINE PreParserExpression
  NewV8Intrinsic(const PreParserIdentifier& name,
                 const PreParserExpressionList& arguments, int pos) {
    return PreParserExpression::Default();
  }

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

  V8_INLINE void AddFormalParameter(PreParserFormalParameters* parameters,
                                    const PreParserExpression& pattern,
                                    const PreParserExpression& initializer,
                                    int initializer_end_position,
                                    bool is_rest) {
    DeclarationScope* scope = parameters->scope;
    scope->RecordParameter(is_rest);
    parameters->UpdateArityAndFunctionLength(!initializer.IsNull(), is_rest);
  }

  V8_INLINE void DeclareFormalParameters(
      const PreParserFormalParameters* parameters) {
    if (!parameters->is_simple) parameters->scope->SetHasNonSimpleParameters();
  }

  V8_INLINE void DeclareArrowFunctionFormalParameters(
      PreParserFormalParameters* parameters, const PreParserExpression& params,
      const Scanner::Location& params_loc) {
  }

  V8_INLINE PreParserExpression
  ExpressionListToExpression(const PreParserExpressionList& args) {
    return PreParserExpression::Default();
  }

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

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

  V8_INLINE bool ParsingDynamicFunctionDeclaration() const { return false; }

// Generate empty functions here as the preparser does not collect source
// ranges for block coverage.
#define DEFINE_RECORD_SOURCE_RANGE(Name) \
  template <typename... Ts>              \
  V8_INLINE void Record##Name##SourceRange(Ts... args) {}
  AST_SOURCE_RANGE_LIST(DEFINE_RECORD_SOURCE_RANGE)
#undef DEFINE_RECORD_SOURCE_RANGE

  // Preparser's private field members.

  int* use_counts_;
  PreParserLogger log_;

  PreparseDataBuilder* preparse_data_builder_;
  std::vector<void*> preparse_data_builder_buffer_;
};

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

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

}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_PREPARSER_H_
