// 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_PARSER_H_
#define V8_PARSING_PARSER_H_

#include <cstddef>

#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast-value-factory.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/base/compiler-specific.h"
#include "src/base/threaded-list.h"
#include "src/common/globals.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/parsing.h"
#include "src/parsing/preparser.h"
#include "src/utils/pointer-with-payload.h"
#include "src/zone/zone-chunk-list.h"

namespace v8 {

class ScriptCompiler;

namespace internal {

class ConsumedPreparseData;
class ParseInfo;
class ParserTarget;
class ParserTargetScope;
class PendingCompilationErrorHandler;
class PreparseData;

// ----------------------------------------------------------------------------
// JAVASCRIPT PARSING

class Parser;


struct ParserFormalParameters : FormalParametersBase {
  struct Parameter : public ZoneObject {
    Parameter(Expression* pattern, Expression* initializer, int position,
              int initializer_end_position, bool is_rest)
        : initializer_and_is_rest(initializer, is_rest),
          pattern(pattern),
          position(position),
          initializer_end_position(initializer_end_position) {}

    PointerWithPayload<Expression, bool, 1> initializer_and_is_rest;

    Expression* pattern;
    Expression* initializer() const {
      return initializer_and_is_rest.GetPointer();
    }
    int position;
    int initializer_end_position;
    inline bool is_rest() const { return initializer_and_is_rest.GetPayload(); }

    Parameter* next_parameter = nullptr;
    bool is_simple() const {
      return pattern->IsVariableProxy() && initializer() == nullptr &&
             !is_rest();
    }

    const AstRawString* name() const {
      DCHECK(is_simple());
      return pattern->AsVariableProxy()->raw_name();
    }

    Parameter** next() { return &next_parameter; }
    Parameter* const* next() const { return &next_parameter; }
  };

  void set_strict_parameter_error(const Scanner::Location& loc,
                                  MessageTemplate message) {
    strict_error_loc = loc;
    strict_error_message = message;
  }

  bool has_duplicate() const { return duplicate_loc.IsValid(); }
  void ValidateDuplicate(Parser* parser) const;
  void ValidateStrictMode(Parser* parser) const;

  explicit ParserFormalParameters(DeclarationScope* scope)
      : FormalParametersBase(scope) {}

  base::ThreadedList<Parameter> params;
  Scanner::Location duplicate_loc = Scanner::Location::invalid();
  Scanner::Location strict_error_loc = Scanner::Location::invalid();
  MessageTemplate strict_error_message = MessageTemplate::kNone;
};

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

  // Return types for traversing functions.
  using Block = v8::internal::Block*;
  using BreakableStatement = v8::internal::BreakableStatement*;
  using ClassLiteralProperty = ClassLiteral::Property*;
  using ClassPropertyList = ZonePtrList<ClassLiteral::Property>*;
  using Expression = v8::internal::Expression*;
  using ExpressionList = ScopedPtrList<v8::internal::Expression>;
  using FormalParameters = ParserFormalParameters;
  using ForStatement = v8::internal::ForStatement*;
  using FunctionLiteral = v8::internal::FunctionLiteral*;
  using Identifier = const AstRawString*;
  using IterationStatement = v8::internal::IterationStatement*;
  using ObjectLiteralProperty = ObjectLiteral::Property*;
  using ObjectPropertyList = ScopedPtrList<v8::internal::ObjectLiteralProperty>;
  using Statement = v8::internal::Statement*;
  using StatementList = ScopedPtrList<v8::internal::Statement>;
  using Suspend = v8::internal::Suspend*;

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

  // Other implementation-specific functions.
  using FuncNameInferrer = v8::internal::FuncNameInferrer;
  using SourceRange = v8::internal::SourceRange;
  using SourceRangeScope = v8::internal::SourceRangeScope;
};

class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
 public:
  explicit Parser(ParseInfo* info);
  ~Parser() {
    delete reusable_preparser_;
    reusable_preparser_ = nullptr;
  }

  static bool IsPreParser() { return false; }

  // Sets the literal on |info| if parsing succeeded.
  void ParseOnBackground(ParseInfo* info, int start_position, int end_position,
                         int function_literal_id);

  // Initializes an empty scope chain for top-level scripts, or scopes which
  // consist of only the native context.
  void InitializeEmptyScopeChain(ParseInfo* info);

  // Deserialize the scope chain prior to parsing in which the script is going
  // to be executed. If the script is a top-level script, or the scope chain
  // consists of only a native context, maybe_outer_scope_info should be an
  // empty handle.
  //
  // This only deserializes the scope chain, but doesn't connect the scopes to
  // their corresponding scope infos. Therefore, looking up variables in the
  // deserialized scopes is not possible.
  void DeserializeScopeChain(Isolate* isolate, ParseInfo* info,
                             MaybeHandle<ScopeInfo> maybe_outer_scope_info,
                             Scope::DeserializationMode mode =
                                 Scope::DeserializationMode::kScopesOnly);

  // Move statistics to Isolate
  void UpdateStatistics(Isolate* isolate, Handle<Script> script);
  template <typename LocalIsolate>
  void HandleSourceURLComments(LocalIsolate* isolate, Handle<Script> script);

 private:
  friend class ParserBase<Parser>;
  friend struct ParserFormalParameters;
  friend class i::ExpressionScope<ParserTypes<Parser>>;
  friend class i::VariableDeclarationParsingScope<ParserTypes<Parser>>;
  friend class i::ParameterDeclarationParsingScope<ParserTypes<Parser>>;
  friend class i::ArrowHeadParsingScope<ParserTypes<Parser>>;
  friend bool v8::internal::parsing::ParseProgram(
      ParseInfo*, Handle<Script>, MaybeHandle<ScopeInfo> maybe_outer_scope_info,
      Isolate*, parsing::ReportStatisticsMode stats_mode);
  friend bool v8::internal::parsing::ParseFunction(
      ParseInfo*, Handle<SharedFunctionInfo> shared_info, Isolate*,
      parsing::ReportStatisticsMode stats_mode);

  bool AllowsLazyParsingWithoutUnresolvedVariables() const {
    return !MaybeParsingArrowhead() &&
           scope()->AllowsLazyParsingWithoutUnresolvedVariables(
               original_scope_);
  }

  bool parse_lazily() const { return mode_ == PARSE_LAZILY; }
  enum Mode { PARSE_LAZILY, PARSE_EAGERLY };

  class ParsingModeScope {
   public:
    ParsingModeScope(Parser* parser, Mode mode)
        : parser_(parser), old_mode_(parser->mode_) {
      parser_->mode_ = mode;
    }
    ~ParsingModeScope() { parser_->mode_ = old_mode_; }

   private:
    Parser* parser_;
    Mode old_mode_;
  };

  // Runtime encoding of different completion modes.
  enum CompletionKind {
    kNormalCompletion,
    kThrowCompletion,
    kAbruptCompletion
  };

  Variable* NewTemporary(const AstRawString* name) {
    return scope()->NewTemporary(name);
  }

  void PrepareGeneratorVariables();

  // Sets the literal on |info| if parsing succeeded.
  void ParseProgram(Isolate* isolate, Handle<Script> script, ParseInfo* info,
                    MaybeHandle<ScopeInfo> maybe_outer_scope_info);

  // Sets the literal on |info| if parsing succeeded.
  void ParseFunction(Isolate* isolate, ParseInfo* info,
                     Handle<SharedFunctionInfo> shared_info);

  void PostProcessParseResult(Isolate* isolate, ParseInfo* info,
                              FunctionLiteral* literal);

  FunctionLiteral* DoParseFunction(Isolate* isolate, ParseInfo* info,
                                   int start_position, int end_position,
                                   int function_literal_id,
                                   const AstRawString* raw_name);

  // Called by ParseProgram after setting up the scanner.
  FunctionLiteral* DoParseProgram(Isolate* isolate, ParseInfo* info);

  // Parse with the script as if the source is implicitly wrapped in a function.
  // We manually construct the AST and scopes for a top-level function and the
  // function wrapper.
  void ParseWrapped(Isolate* isolate, ParseInfo* info,
                    ScopedPtrList<Statement>* body, DeclarationScope* scope,
                    Zone* zone);

  void ParseREPLProgram(ParseInfo* info, ScopedPtrList<Statement>* body,
                        DeclarationScope* scope);
  Expression* WrapREPLResult(Expression* value);

  ZonePtrList<const AstRawString>* PrepareWrappedArguments(Isolate* isolate,
                                                           ParseInfo* info,
                                                           Zone* zone);

  PreParser* reusable_preparser() {
    if (reusable_preparser_ == nullptr) {
      reusable_preparser_ = new PreParser(
          &preparser_zone_, &scanner_, stack_limit_, ast_value_factory(),
          pending_error_handler(), runtime_call_stats_, logger_, flags(),
          parsing_on_main_thread_);
      reusable_preparser_->set_allow_eval_cache(allow_eval_cache());
      preparse_data_buffer_.reserve(128);
    }
    return reusable_preparser_;
  }

  void ParseModuleItemList(ScopedPtrList<Statement>* body);
  Statement* ParseModuleItem();
  const AstRawString* ParseModuleSpecifier();
  void ParseImportDeclaration();
  Statement* ParseExportDeclaration();
  Statement* ParseExportDefault();
  void ParseExportStar();
  struct ExportClauseData {
    const AstRawString* export_name;
    const AstRawString* local_name;
    Scanner::Location location;
  };
  ZoneChunkList<ExportClauseData>* ParseExportClause(
      Scanner::Location* reserved_loc,
      Scanner::Location* string_literal_local_name_loc);
  struct NamedImport : public ZoneObject {
    const AstRawString* import_name;
    const AstRawString* local_name;
    const Scanner::Location location;
    NamedImport(const AstRawString* import_name, const AstRawString* local_name,
                Scanner::Location location)
        : import_name(import_name),
          local_name(local_name),
          location(location) {}
  };
  const AstRawString* ParseExportSpecifierName();
  ZonePtrList<const NamedImport>* ParseNamedImports(int pos);
  using ImportAssertions =
      ZoneMap<const AstRawString*,
              std::pair<const AstRawString*, Scanner::Location>>;
  ImportAssertions* ParseImportAssertClause();
  Statement* BuildInitializationBlock(DeclarationParsingResult* parsing_result);
  Expression* RewriteReturn(Expression* return_value, int pos);
  Statement* RewriteSwitchStatement(SwitchStatement* switch_statement,
                                    Scope* scope);
  Block* RewriteCatchPattern(CatchInfo* catch_info);
  void ReportVarRedeclarationIn(const AstRawString* name, Scope* scope);
  Statement* RewriteTryStatement(Block* try_block, Block* catch_block,
                                 const SourceRange& catch_range,
                                 Block* finally_block,
                                 const SourceRange& finally_range,
                                 const CatchInfo& catch_info, int pos);
  void ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind,
                                            ScopedPtrList<Statement>* body);
  void ParseAndRewriteAsyncGeneratorFunctionBody(
      int pos, FunctionKind kind, ScopedPtrList<Statement>* body);
  void DeclareFunctionNameVar(const AstRawString* function_name,
                              FunctionSyntaxKind function_syntax_kind,
                              DeclarationScope* function_scope);

  Statement* DeclareFunction(const AstRawString* variable_name,
                             FunctionLiteral* function, VariableMode mode,
                             VariableKind kind, int beg_pos, int end_pos,
                             ZonePtrList<const AstRawString>* names);
  Variable* CreateSyntheticContextVariable(const AstRawString* synthetic_name);
  Variable* CreatePrivateNameVariable(ClassScope* scope, VariableMode mode,
                                      IsStaticFlag is_static_flag,
                                      const AstRawString* name);
  FunctionLiteral* CreateInitializerFunction(
      const char* name, DeclarationScope* scope,
      ZonePtrList<ClassLiteral::Property>* fields);

  bool IdentifierEquals(const AstRawString* identifier,
                        const AstRawString* other) {
    return identifier == other;
  }

  Statement* DeclareClass(const AstRawString* variable_name, Expression* value,
                          ZonePtrList<const AstRawString>* names,
                          int class_token_pos, int end_pos);
  void DeclareClassVariable(ClassScope* scope, const AstRawString* name,
                            ClassInfo* class_info, int class_token_pos);
  void DeclareClassBrandVariable(ClassScope* scope, ClassInfo* class_info,
                                 int class_token_pos);
  void DeclarePrivateClassMember(ClassScope* scope,
                                 const AstRawString* property_name,
                                 ClassLiteralProperty* property,
                                 ClassLiteralProperty::Kind kind,
                                 bool is_static, ClassInfo* class_info);
  void DeclarePublicClassMethod(const AstRawString* class_name,
                                ClassLiteralProperty* property,
                                bool is_constructor, ClassInfo* class_info);
  void DeclarePublicClassField(ClassScope* scope,
                               ClassLiteralProperty* property, bool is_static,
                               bool is_computed_name, ClassInfo* class_info);
  void DeclareClassProperty(ClassScope* scope, const AstRawString* class_name,
                            ClassLiteralProperty* property, bool is_constructor,
                            ClassInfo* class_info);
  void DeclareClassField(ClassScope* scope, ClassLiteralProperty* property,
                         const AstRawString* property_name, bool is_static,
                         bool is_computed_name, bool is_private,
                         ClassInfo* class_info);
  Expression* RewriteClassLiteral(ClassScope* block_scope,
                                  const AstRawString* name,
                                  ClassInfo* class_info, int pos, int end_pos);
  Statement* DeclareNative(const AstRawString* name, int pos);

  Block* IgnoreCompletion(Statement* statement);

  Scope* NewHiddenCatchScope();

  bool HasCheckedSyntax() {
    return scope()->GetDeclarationScope()->has_checked_syntax();
  }

  void InitializeVariables(
      ScopedPtrList<Statement>* statements, VariableKind kind,
      const DeclarationParsingResult::Declaration* declaration);

  Block* RewriteForVarInLegacy(const ForInfo& for_info);
  void DesugarBindingInForEachStatement(ForInfo* for_info, Block** body_block,
                                        Expression** each_variable);
  Block* CreateForEachStatementTDZ(Block* init_block, const ForInfo& for_info);

  Statement* DesugarLexicalBindingsInForStatement(
      ForStatement* loop, Statement* init, Expression* cond, Statement* next,
      Statement* body, Scope* inner_scope, const ForInfo& for_info);

  FunctionLiteral* ParseFunctionLiteral(
      const AstRawString* name, Scanner::Location function_name_location,
      FunctionNameValidity function_name_validity, FunctionKind kind,
      int function_token_position, FunctionSyntaxKind type,
      LanguageMode language_mode,
      ZonePtrList<const AstRawString>* arguments_for_wrapped_function);

  ObjectLiteral* InitializeObjectLiteral(ObjectLiteral* object_literal) {
    object_literal->CalculateEmitStore(main_zone());
    return object_literal;
  }

  // Insert initializer statements for var-bindings shadowing parameter bindings
  // from a non-simple parameter list.
  void InsertShadowingVarBindingInitializers(Block* block);

  // Implement sloppy block-scoped functions, ES2015 Annex B 3.3
  void InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope);

  void DeclareUnboundVariable(const AstRawString* name, VariableMode mode,
                              InitializationFlag init, int pos);
  V8_WARN_UNUSED_RESULT
  VariableProxy* DeclareBoundVariable(const AstRawString* name,
                                      VariableMode mode, int pos);
  void DeclareAndBindVariable(VariableProxy* proxy, VariableKind kind,
                              VariableMode mode, Scope* declaration_scope,
                              bool* was_added, int initializer_position);
  V8_WARN_UNUSED_RESULT
  Variable* DeclareVariable(const AstRawString* name, VariableKind kind,
                            VariableMode mode, InitializationFlag init,
                            Scope* declaration_scope, bool* was_added,
                            int begin, int end = kNoSourcePosition);
  void Declare(Declaration* declaration, const AstRawString* name,
               VariableKind kind, VariableMode mode, InitializationFlag init,
               Scope* declaration_scope, bool* was_added, int var_begin_pos,
               int var_end_pos = kNoSourcePosition);

  // Factory methods.
  FunctionLiteral* DefaultConstructor(const AstRawString* name, bool call_super,
                                      int pos, int end_pos);

  // Skip over a lazy function, either using cached data if we have it, or
  // by parsing the function with PreParser. Consumes the ending }.
  // In case the preparser detects an error it cannot identify, it resets the
  // scanner- and preparser state to the initial one, before PreParsing the
  // function.
  // SkipFunction returns true if it correctly parsed the function, including
  // cases where we detect an error. It returns false, if we needed to stop
  // parsing or could not identify an error correctly, meaning the caller needs
  // to fully reparse. In this case it resets the scanner and preparser state.
  bool SkipFunction(const AstRawString* function_name, FunctionKind kind,
                    FunctionSyntaxKind function_syntax_kind,
                    DeclarationScope* function_scope, int* num_parameters,
                    int* function_length,
                    ProducedPreparseData** produced_preparsed_scope_data);

  Block* BuildParameterInitializationBlock(
      const ParserFormalParameters& parameters);
  Block* BuildRejectPromiseOnException(Block* block,
                                       REPLMode repl_mode = REPLMode::kNo);

  void ParseFunction(
      ScopedPtrList<Statement>* body, const AstRawString* function_name,
      int pos, FunctionKind kind, FunctionSyntaxKind function_syntax_kind,
      DeclarationScope* function_scope, int* num_parameters,
      int* function_length, bool* has_duplicate_parameters,
      int* expected_property_count, int* suspend_count,
      ZonePtrList<const AstRawString>* arguments_for_wrapped_function);

  void ThrowPendingError(Isolate* isolate, Handle<Script> script);

  class TemplateLiteral : public ZoneObject {
   public:
    TemplateLiteral(Zone* zone, int pos)
        : cooked_(8, zone), raw_(8, zone), expressions_(8, zone), pos_(pos) {}

    const ZonePtrList<const AstRawString>* cooked() const { return &cooked_; }
    const ZonePtrList<const AstRawString>* raw() const { return &raw_; }
    const ZonePtrList<Expression>* expressions() const { return &expressions_; }
    int position() const { return pos_; }

    void AddTemplateSpan(const AstRawString* cooked, const AstRawString* raw,
                         int end, Zone* zone) {
      DCHECK_NOT_NULL(raw);
      cooked_.Add(cooked, zone);
      raw_.Add(raw, zone);
    }

    void AddExpression(Expression* expression, Zone* zone) {
      expressions_.Add(expression, zone);
    }

   private:
    ZonePtrList<const AstRawString> cooked_;
    ZonePtrList<const AstRawString> raw_;
    ZonePtrList<Expression> expressions_;
    int pos_;
  };

  using TemplateLiteralState = TemplateLiteral*;

  TemplateLiteralState OpenTemplateLiteral(int pos);
  // "should_cook" means that the span can be "cooked": in tagged template
  // literals, both the raw and "cooked" representations are available to user
  // code ("cooked" meaning that escape sequences are converted to their
  // interpreted values). Invalid escape sequences cause the cooked span
  // to be represented by undefined, instead of being a syntax error.
  // "tail" indicates that this span is the last in the literal.
  void AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
                       bool tail);
  void AddTemplateExpression(TemplateLiteralState* state,
                             Expression* expression);
  Expression* CloseTemplateLiteral(TemplateLiteralState* state, int start,
                                   Expression* tag);

  ArrayLiteral* ArrayLiteralFromListWithSpread(
      const ScopedPtrList<Expression>& list);
  Expression* SpreadCall(Expression* function,
                         const ScopedPtrList<Expression>& args, int pos,
                         Call::PossiblyEval is_possibly_eval,
                         bool optional_chain);
  Expression* SpreadCallNew(Expression* function,
                            const ScopedPtrList<Expression>& args, int pos);
  Expression* RewriteSuperCall(Expression* call_expression);

  void SetLanguageMode(Scope* scope, LanguageMode mode);
  void SetAsmModule();

  Expression* RewriteSpreads(ArrayLiteral* lit);

  Expression* BuildInitialYield(int pos, FunctionKind kind);
  Assignment* BuildCreateJSGeneratorObject(int pos, FunctionKind kind);

  // Generic AST generator for throwing errors from compiled code.
  Expression* NewThrowError(Runtime::FunctionId function_id,
                            MessageTemplate message, const AstRawString* arg,
                            int pos);

  Statement* CheckCallable(Variable* var, Expression* error, int pos);

  void RewriteAsyncFunctionBody(ScopedPtrList<Statement>* body, Block* block,
                                Expression* return_value,
                                REPLMode repl_mode = REPLMode::kNo);

  void AddArrowFunctionFormalParameters(ParserFormalParameters* parameters,
                                        Expression* params, int end_pos);
  void SetFunctionName(Expression* value, const AstRawString* name,
                       const AstRawString* prefix = nullptr);

  // Helper functions for recursive descent.
  V8_INLINE bool IsEval(const AstRawString* identifier) const {
    return identifier == ast_value_factory()->eval_string();
  }

  V8_INLINE bool IsAsync(const AstRawString* identifier) const {
    return identifier == ast_value_factory()->async_string();
  }

  V8_INLINE bool IsArguments(const AstRawString* identifier) const {
    return identifier == ast_value_factory()->arguments_string();
  }

  V8_INLINE bool IsEvalOrArguments(const AstRawString* identifier) const {
    return IsEval(identifier) || IsArguments(identifier);
  }

  // Returns true if the expression is of type "this.foo".
  V8_INLINE static bool IsThisProperty(Expression* expression) {
    DCHECK_NOT_NULL(expression);
    Property* property = expression->AsProperty();
    return property != nullptr && property->obj()->IsThisExpression();
  }

  // Returns true if the expression is of type "obj.#foo" or "obj?.#foo".
  V8_INLINE static bool IsPrivateReference(Expression* expression) {
    DCHECK_NOT_NULL(expression);
    Property* property = expression->AsProperty();
    if (expression->IsOptionalChain()) {
      Expression* expr_inner = expression->AsOptionalChain()->expression();
      property = expr_inner->AsProperty();
    }
    return property != nullptr && property->IsPrivateReference();
  }

  // This returns true if the expression is an indentifier (wrapped
  // inside a variable proxy).  We exclude the case of 'this', which
  // has been converted to a variable proxy.
  V8_INLINE static bool IsIdentifier(Expression* expression) {
    VariableProxy* operand = expression->AsVariableProxy();
    return operand != nullptr && !operand->is_new_target();
  }

  V8_INLINE static const AstRawString* AsIdentifier(Expression* expression) {
    DCHECK(IsIdentifier(expression));
    return expression->AsVariableProxy()->raw_name();
  }

  V8_INLINE VariableProxy* AsIdentifierExpression(Expression* expression) {
    return expression->AsVariableProxy();
  }

  V8_INLINE bool IsConstructor(const AstRawString* identifier) const {
    return identifier == ast_value_factory()->constructor_string();
  }

  V8_INLINE bool IsName(const AstRawString* identifier) const {
    return identifier == ast_value_factory()->name_string();
  }

  V8_INLINE static bool IsBoilerplateProperty(
      ObjectLiteral::Property* property) {
    return !property->IsPrototype();
  }

  V8_INLINE bool IsNative(Expression* expr) const {
    DCHECK_NOT_NULL(expr);
    return expr->IsVariableProxy() &&
           expr->AsVariableProxy()->raw_name() ==
               ast_value_factory()->native_string();
  }

  V8_INLINE static bool IsArrayIndex(const AstRawString* string,
                                     uint32_t* index) {
    return string->AsArrayIndex(index);
  }

  // Returns true if the statement is an expression statement containing
  // a single string literal.  If a second argument is given, the literal
  // is also compared with it and the result is true only if they are equal.
  V8_INLINE bool IsStringLiteral(Statement* statement,
                                 const AstRawString* arg = nullptr) const {
    ExpressionStatement* e_stat = statement->AsExpressionStatement();
    if (e_stat == nullptr) return false;
    Literal* literal = e_stat->expression()->AsLiteral();
    if (literal == nullptr || !literal->IsString()) return false;
    return arg == nullptr || literal->AsRawString() == arg;
  }

  V8_INLINE void GetDefaultStrings(const AstRawString** default_string,
                                   const AstRawString** dot_default_string) {
    *default_string = ast_value_factory()->default_string();
    *dot_default_string = ast_value_factory()->dot_default_string();
  }

  // Functions for encapsulating the differences between parsing and preparsing;
  // operations interleaved with the recursive descent.
  V8_INLINE void PushLiteralName(const AstRawString* id) {
    fni_.PushLiteralName(id);
  }

  V8_INLINE void PushVariableName(const AstRawString* id) {
    fni_.PushVariableName(id);
  }

  V8_INLINE void PushPropertyName(Expression* expression) {
    if (expression->IsPropertyName()) {
      fni_.PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
    } else {
      fni_.PushLiteralName(ast_value_factory()->computed_string());
    }
  }

  V8_INLINE void PushEnclosingName(const AstRawString* name) {
    fni_.PushEnclosingName(name);
  }

  V8_INLINE void AddFunctionForNameInference(FunctionLiteral* func_to_infer) {
    fni_.AddFunction(func_to_infer);
  }

  V8_INLINE void InferFunctionName() { fni_.Infer(); }

  // If we assign a function literal to a property we pretenure the
  // literal so it can be added as a constant function property.
  V8_INLINE static void CheckAssigningFunctionLiteralToProperty(
      Expression* left, Expression* right) {
    DCHECK_NOT_NULL(left);
    if (left->IsProperty() && right->IsFunctionLiteral()) {
      right->AsFunctionLiteral()->set_pretenure();
    }
  }

  // A shortcut for performing a ToString operation
  V8_INLINE Expression* ToString(Expression* expr) {
    if (expr->IsStringLiteral()) return expr;
    ScopedPtrList<Expression> args(pointer_buffer());
    args.Add(expr);
    return factory()->NewCallRuntime(Runtime::kInlineToString, args,
                                     expr->position());
  }

  // Returns true if we have a binary expression between two numeric
  // literals. In that case, *x will be changed to an expression which is the
  // computed value.
  bool ShortcutNumericLiteralBinaryExpression(Expression** x, Expression* y,
                                              Token::Value op, int pos);

  // Returns true if we have a binary operation between a binary/n-ary
  // expression (with the same operation) and a value, which can be collapsed
  // into a single n-ary expression. In that case, *x will be changed to an
  // n-ary expression.
  bool CollapseNaryExpression(Expression** x, Expression* y, Token::Value op,
                              int pos, const SourceRange& range);

  // Returns a UnaryExpression or, in one of the following cases, a Literal.
  // ! <literal> -> true / false
  // + <Number literal> -> <Number literal>
  // - <Number literal> -> <Number literal with value negated>
  // ~ <literal> -> true / false
  Expression* BuildUnaryExpression(Expression* expression, Token::Value op,
                                   int pos);

  // Generate AST node that throws a ReferenceError with the given type.
  V8_INLINE Expression* NewThrowReferenceError(MessageTemplate message,
                                               int pos) {
    return NewThrowError(Runtime::kNewReferenceError, message,
                         ast_value_factory()->empty_string(), pos);
  }

  // Generate AST node that throws a SyntaxError with the given
  // type. The first argument may be null (in the handle sense) in
  // which case no arguments are passed to the constructor.
  V8_INLINE Expression* NewThrowSyntaxError(MessageTemplate message,
                                            const AstRawString* arg, int pos) {
    return NewThrowError(Runtime::kNewSyntaxError, message, arg, pos);
  }

  // Generate AST node that throws a TypeError with the given
  // type. Both arguments must be non-null (in the handle sense).
  V8_INLINE Expression* NewThrowTypeError(MessageTemplate message,
                                          const AstRawString* arg, int pos) {
    return NewThrowError(Runtime::kNewTypeError, message, arg, pos);
  }

  // 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();
  }

  // Dummy implementation. The parser should never have a unidentifiable
  // error.
  V8_INLINE void ReportUnidentifiableError() { UNREACHABLE(); }

  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 AstRawString* arg) {
    return arg;
  }

  IterationStatement* AsIterationStatement(BreakableStatement* s) {
    return s->AsIterationStatement();
  }

  void ReportUnexpectedTokenAt(
      Scanner::Location location, Token::Value token,
      MessageTemplate message = MessageTemplate::kUnexpectedToken);

  // "null" return type creators.
  V8_INLINE static std::nullptr_t NullIdentifier() { return nullptr; }
  V8_INLINE static std::nullptr_t NullExpression() { return nullptr; }
  V8_INLINE static std::nullptr_t NullLiteralProperty() { return nullptr; }
  V8_INLINE static ZonePtrList<Expression>* NullExpressionList() {
    return nullptr;
  }
  V8_INLINE static ZonePtrList<Statement>* NullStatementList() {
    return nullptr;
  }
  V8_INLINE static std::nullptr_t NullStatement() { return nullptr; }
  V8_INLINE static std::nullptr_t NullBlock() { return nullptr; }
  Expression* FailureExpression() { return factory()->FailureExpression(); }

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

  V8_INLINE static bool IsIterationStatement(Statement* subject) {
    return subject->AsIterationStatement() != nullptr;
  }

  // Non-null empty string.
  V8_INLINE const AstRawString* EmptyIdentifierString() const {
    return ast_value_factory()->empty_string();
  }

  // Producing data during the recursive descent.
  V8_INLINE const AstRawString* GetSymbol() const {
    const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
    DCHECK_NOT_NULL(result);
    return result;
  }

  V8_INLINE const AstRawString* GetIdentifier() const { return GetSymbol(); }

  V8_INLINE const AstRawString* GetNextSymbol() const {
    return scanner()->NextSymbol(ast_value_factory());
  }

  V8_INLINE const AstRawString* GetNumberAsSymbol() const {
    double double_value = scanner()->DoubleValue();
    char array[100];
    const char* string = DoubleToCString(double_value, ArrayVector(array));
    return ast_value_factory()->GetOneByteString(string);
  }

  class ThisExpression* ThisExpression() {
    UseThis();
    return factory()->ThisExpression();
  }

  class ThisExpression* NewThisExpression(int pos) {
    UseThis();
    return factory()->NewThisExpression(pos);
  }

  Expression* NewSuperPropertyReference(int pos);
  Expression* NewSuperCallReference(int pos);
  Expression* NewTargetExpression(int pos);
  Expression* ImportMetaExpression(int pos);

  Expression* ExpressionFromLiteral(Token::Value token, int pos);

  V8_INLINE VariableProxy* ExpressionFromPrivateName(
      PrivateNameScopeIterator* private_name_scope, const AstRawString* name,
      int start_position) {
    VariableProxy* proxy = factory()->ast_node_factory()->NewVariableProxy(
        name, NORMAL_VARIABLE, start_position);
    private_name_scope->AddUnresolvedPrivateName(proxy);
    return proxy;
  }

  V8_INLINE VariableProxy* ExpressionFromIdentifier(
      const AstRawString* name, int start_position,
      InferName infer = InferName::kYes) {
    if (infer == InferName::kYes) {
      fni_.PushVariableName(name);
    }
    return expression_scope()->NewVariable(name, start_position);
  }

  V8_INLINE void DeclareIdentifier(const AstRawString* name,
                                   int start_position) {
    expression_scope()->Declare(name, start_position);
  }

  V8_INLINE Variable* DeclareCatchVariableName(Scope* scope,
                                               const AstRawString* name) {
    return scope->DeclareCatchVariableName(name);
  }

  V8_INLINE ZonePtrList<Expression>* NewExpressionList(int size) const {
    return zone()->New<ZonePtrList<Expression>>(size, zone());
  }
  V8_INLINE ZonePtrList<ObjectLiteral::Property>* NewObjectPropertyList(
      int size) const {
    return zone()->New<ZonePtrList<ObjectLiteral::Property>>(size, zone());
  }
  V8_INLINE ZonePtrList<ClassLiteral::Property>* NewClassPropertyList(
      int size) const {
    return zone()->New<ZonePtrList<ClassLiteral::Property>>(size, zone());
  }
  V8_INLINE ZonePtrList<Statement>* NewStatementList(int size) const {
    return zone()->New<ZonePtrList<Statement>>(size, zone());
  }

  Expression* NewV8Intrinsic(const AstRawString* name,
                             const ScopedPtrList<Expression>& args, int pos);

  Expression* NewV8RuntimeFunctionForFuzzing(
      const Runtime::Function* function, const ScopedPtrList<Expression>& args,
      int pos);

  V8_INLINE Statement* NewThrowStatement(Expression* exception, int pos) {
    return factory()->NewExpressionStatement(
        factory()->NewThrow(exception, pos), pos);
  }

  V8_INLINE void AddFormalParameter(ParserFormalParameters* parameters,
                                    Expression* pattern,
                                    Expression* initializer,
                                    int initializer_end_position,
                                    bool is_rest) {
    parameters->UpdateArityAndFunctionLength(initializer != nullptr, is_rest);
    auto parameter =
        parameters->scope->zone()->New<ParserFormalParameters::Parameter>(
            pattern, initializer, scanner()->location().beg_pos,
            initializer_end_position, is_rest);

    parameters->params.Add(parameter);
  }

  V8_INLINE void DeclareFormalParameters(ParserFormalParameters* parameters) {
    bool is_simple = parameters->is_simple;
    DeclarationScope* scope = parameters->scope;
    if (!is_simple) scope->MakeParametersNonSimple();
    for (auto parameter : parameters->params) {
      bool is_optional = parameter->initializer() != nullptr;
      // If the parameter list is simple, declare the parameters normally with
      // their names. If the parameter list is not simple, declare a temporary
      // for each parameter - the corresponding named variable is declared by
      // BuildParamerterInitializationBlock.
      scope->DeclareParameter(
          is_simple ? parameter->name() : ast_value_factory()->empty_string(),
          is_simple ? VariableMode::kVar : VariableMode::kTemporary,
          is_optional, parameter->is_rest(), ast_value_factory(),
          parameter->position);
    }
  }

  void DeclareArrowFunctionFormalParameters(
      ParserFormalParameters* parameters, Expression* params,
      const Scanner::Location& params_loc);

  Expression* ExpressionListToExpression(const ScopedPtrList<Expression>& args);

  void SetFunctionNameFromPropertyName(LiteralProperty* property,
                                       const AstRawString* name,
                                       const AstRawString* prefix = nullptr);
  void SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
                                       const AstRawString* name,
                                       const AstRawString* prefix = nullptr);

  void SetFunctionNameFromIdentifierRef(Expression* value,
                                        Expression* identifier);

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

  // Returns true iff we're parsing the first function literal during
  // CreateDynamicFunction().
  V8_INLINE bool ParsingDynamicFunctionDeclaration() const {
    return parameters_end_pos_ != kNoSourcePosition;
  }

  V8_INLINE void ConvertBinaryToNaryOperationSourceRange(
      BinaryOperation* binary_op, NaryOperation* nary_op) {
    if (source_range_map_ == nullptr) return;
    DCHECK_NULL(source_range_map_->Find(nary_op));

    BinaryOperationSourceRanges* ranges =
        static_cast<BinaryOperationSourceRanges*>(
            source_range_map_->Find(binary_op));
    if (ranges == nullptr) return;

    SourceRange range = ranges->GetRange(SourceRangeKind::kRight);
    source_range_map_->Insert(
        nary_op, zone()->New<NaryOperationSourceRanges>(zone(), range));
  }

  V8_INLINE void AppendNaryOperationSourceRange(NaryOperation* node,
                                                const SourceRange& range) {
    if (source_range_map_ == nullptr) return;
    NaryOperationSourceRanges* ranges =
        static_cast<NaryOperationSourceRanges*>(source_range_map_->Find(node));
    if (ranges == nullptr) return;

    ranges->AddRange(range);
    DCHECK_EQ(node->subsequent_length(), ranges->RangeCount());
  }

  V8_INLINE void RecordBlockSourceRange(Block* node,
                                        int32_t continuation_position) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node, zone()->New<BlockSourceRanges>(continuation_position));
  }

  V8_INLINE void RecordCaseClauseSourceRange(CaseClause* node,
                                             const SourceRange& body_range) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(node,
                              zone()->New<CaseClauseSourceRanges>(body_range));
  }

  V8_INLINE void RecordConditionalSourceRange(Expression* node,
                                              const SourceRange& then_range,
                                              const SourceRange& else_range) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node->AsConditional(),
        zone()->New<ConditionalSourceRanges>(then_range, else_range));
  }

  V8_INLINE void RecordFunctionLiteralSourceRange(FunctionLiteral* node) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(node, zone()->New<FunctionLiteralSourceRanges>());
  }

  V8_INLINE void RecordBinaryOperationSourceRange(
      Expression* node, const SourceRange& right_range) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node->AsBinaryOperation(),
        zone()->New<BinaryOperationSourceRanges>(right_range));
  }

  V8_INLINE void RecordJumpStatementSourceRange(Statement* node,
                                                int32_t continuation_position) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        static_cast<JumpStatement*>(node),
        zone()->New<JumpStatementSourceRanges>(continuation_position));
  }

  V8_INLINE void RecordIfStatementSourceRange(Statement* node,
                                              const SourceRange& then_range,
                                              const SourceRange& else_range) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node->AsIfStatement(),
        zone()->New<IfStatementSourceRanges>(then_range, else_range));
  }

  V8_INLINE void RecordIterationStatementSourceRange(
      IterationStatement* node, const SourceRange& body_range) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node, zone()->New<IterationStatementSourceRanges>(body_range));
  }

  V8_INLINE void RecordSuspendSourceRange(Expression* node,
                                          int32_t continuation_position) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        static_cast<Suspend*>(node),
        zone()->New<SuspendSourceRanges>(continuation_position));
  }

  V8_INLINE void RecordSwitchStatementSourceRange(
      Statement* node, int32_t continuation_position) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node->AsSwitchStatement(),
        zone()->New<SwitchStatementSourceRanges>(continuation_position));
  }

  V8_INLINE void RecordThrowSourceRange(Statement* node,
                                        int32_t continuation_position) {
    if (source_range_map_ == nullptr) return;
    ExpressionStatement* expr_stmt = static_cast<ExpressionStatement*>(node);
    Throw* throw_expr = expr_stmt->expression()->AsThrow();
    source_range_map_->Insert(
        throw_expr, zone()->New<ThrowSourceRanges>(continuation_position));
  }

  V8_INLINE void RecordTryCatchStatementSourceRange(
      TryCatchStatement* node, const SourceRange& body_range) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node, zone()->New<TryCatchStatementSourceRanges>(body_range));
  }

  V8_INLINE void RecordTryFinallyStatementSourceRange(
      TryFinallyStatement* node, const SourceRange& body_range) {
    if (source_range_map_ == nullptr) return;
    source_range_map_->Insert(
        node, zone()->New<TryFinallyStatementSourceRanges>(body_range));
  }

  // Generate the next internal variable name for binding an exported namespace
  // object (used to implement the "export * as" syntax).
  const AstRawString* NextInternalNamespaceExportName();

  ParseInfo* info() const { return info_; }

  std::vector<uint8_t>* preparse_data_buffer() {
    return &preparse_data_buffer_;
  }

  // Parser's private field members.
  friend class PreParserZoneScope;  // Uses reusable_preparser().
  friend class PreparseDataBuilder;  // Uses preparse_data_buffer()

  ParseInfo* info_;
  Scanner scanner_;
  Zone preparser_zone_;
  PreParser* reusable_preparser_;
  Mode mode_;

  MaybeHandle<FixedArray> maybe_wrapped_arguments_;

  SourceRangeMap* source_range_map_ = nullptr;

  friend class ParserTargetScope;

  ScriptCompiler::CompileOptions compile_options_;

  // For NextInternalNamespaceExportName().
  int number_of_named_namespace_exports_ = 0;

  // Other information which will be stored in Parser and moved to Isolate after
  // parsing.
  int use_counts_[v8::Isolate::kUseCounterFeatureCount];
  int total_preparse_skipped_;
  bool allow_lazy_;
  bool temp_zoned_;
  ConsumedPreparseData* consumed_preparse_data_;
  std::vector<uint8_t> preparse_data_buffer_;

  // If not kNoSourcePosition, indicates that the first function literal
  // encountered is a dynamic function, see CreateDynamicFunction(). This field
  // indicates the correct position of the ')' that closes the parameter list.
  // After that ')' is encountered, this field is reset to kNoSourcePosition.
  int parameters_end_pos_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_PARSER_H_
