// 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 "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/preparse-data.h"
#include "src/parsing/preparse-data-format.h"
#include "src/parsing/preparser.h"
#include "src/pending-compilation-error-handler.h"

namespace v8 {

class ScriptCompiler;

namespace internal {

class ParseInfo;
class ScriptData;
class ParserTarget;
class ParserTargetScope;

class FunctionEntry BASE_EMBEDDED {
 public:
  enum {
    kStartPositionIndex,
    kEndPositionIndex,
    kLiteralCountIndex,
    kPropertyCountIndex,
    kLanguageModeIndex,
    kUsesSuperPropertyIndex,
    kCallsEvalIndex,
    kSize
  };

  explicit FunctionEntry(Vector<unsigned> backing)
    : backing_(backing) { }

  FunctionEntry() : backing_() { }

  int start_pos() { return backing_[kStartPositionIndex]; }
  int end_pos() { return backing_[kEndPositionIndex]; }
  int literal_count() { return backing_[kLiteralCountIndex]; }
  int property_count() { return backing_[kPropertyCountIndex]; }
  LanguageMode language_mode() {
    DCHECK(is_valid_language_mode(backing_[kLanguageModeIndex]));
    return static_cast<LanguageMode>(backing_[kLanguageModeIndex]);
  }
  bool uses_super_property() { return backing_[kUsesSuperPropertyIndex]; }
  bool calls_eval() { return backing_[kCallsEvalIndex]; }

  bool is_valid() { return !backing_.is_empty(); }

 private:
  Vector<unsigned> backing_;
};


// Wrapper around ScriptData to provide parser-specific functionality.
class ParseData {
 public:
  static ParseData* FromCachedData(ScriptData* cached_data) {
    ParseData* pd = new ParseData(cached_data);
    if (pd->IsSane()) return pd;
    cached_data->Reject();
    delete pd;
    return NULL;
  }

  void Initialize();
  FunctionEntry GetFunctionEntry(int start);
  int FunctionCount();

  bool HasError();

  unsigned* Data() {  // Writable data as unsigned int array.
    return reinterpret_cast<unsigned*>(const_cast<byte*>(script_data_->data()));
  }

  void Reject() { script_data_->Reject(); }

  bool rejected() const { return script_data_->rejected(); }

 private:
  explicit ParseData(ScriptData* script_data) : script_data_(script_data) {}

  bool IsSane();
  unsigned Magic();
  unsigned Version();
  int FunctionsSize();
  int Length() const {
    // Script data length is already checked to be a multiple of unsigned size.
    return script_data_->length() / sizeof(unsigned);
  }

  ScriptData* script_data_;
  int function_index_;

  DISALLOW_COPY_AND_ASSIGN(ParseData);
};

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

class Parser;
class SingletonLogger;


struct ParserFormalParameters : FormalParametersBase {
  struct Parameter {
    Parameter(const AstRawString* name, Expression* pattern,
              Expression* initializer, int initializer_end_position,
              bool is_rest)
        : name(name),
          pattern(pattern),
          initializer(initializer),
          initializer_end_position(initializer_end_position),
          is_rest(is_rest) {}
    const AstRawString* name;
    Expression* pattern;
    Expression* initializer;
    int initializer_end_position;
    bool is_rest;
    bool is_simple() const {
      return pattern->IsVariableProxy() && initializer == nullptr && !is_rest;
    }
  };

  explicit ParserFormalParameters(DeclarationScope* scope)
      : FormalParametersBase(scope), params(4, scope->zone()) {}
  ZoneList<Parameter> params;

  int Arity() const { return params.length(); }
  const Parameter& at(int i) const { return params[i]; }
};

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

  typedef Variable GeneratorVariable;

  // Return types for traversing functions.
  typedef const AstRawString* Identifier;
  typedef v8::internal::Expression* Expression;
  typedef v8::internal::FunctionLiteral* FunctionLiteral;
  typedef ObjectLiteral::Property* ObjectLiteralProperty;
  typedef ClassLiteral::Property* ClassLiteralProperty;
  typedef ZoneList<v8::internal::Expression*>* ExpressionList;
  typedef ZoneList<ObjectLiteral::Property*>* PropertyList;
  typedef ParserFormalParameters FormalParameters;
  typedef v8::internal::Statement* Statement;
  typedef ZoneList<v8::internal::Statement*>* StatementList;
  typedef v8::internal::Block* Block;
  typedef v8::internal::BreakableStatement* BreakableStatement;
  typedef v8::internal::IterationStatement* IterationStatement;

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

  typedef ParserTarget Target;
  typedef ParserTargetScope TargetScope;
};

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

  // Parses the source code represented by the compilation info and sets its
  // function literal.  Returns false (and deallocates any allocated AST
  // nodes) if parsing failed.
  static bool ParseStatic(ParseInfo* info);
  bool Parse(ParseInfo* info);
  void ParseOnBackground(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(ParseInfo* info,
                             MaybeHandle<ScopeInfo> maybe_outer_scope_info);

  // Handle errors detected during parsing, move statistics to Isolate,
  // internalize strings (move them to the heap).
  void Internalize(Isolate* isolate, Handle<Script> script, bool error);
  void HandleSourceURLComments(Isolate* isolate, Handle<Script> script);

 private:
  friend class ParserBase<Parser>;
  friend class v8::internal::ExpressionClassifier<ParserTypes<Parser>>;

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

  enum class FunctionBodyType { kNormal, kSingleExpression };

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

  // Limit the allowed number of local variables in a function. The hard limit
  // is that offsets computed by FullCodeGenerator::StackOperand and similar
  // functions are ints, and they should not overflow. In addition, accessing
  // local variables creates user-controlled constants in the generated code,
  // and we don't want too much user-controlled memory inside the code (this was
  // the reason why this limit was introduced in the first place; see
  // https://codereview.chromium.org/7003030/ ).
  static const int kMaxNumFunctionLocals = 4194303;  // 2^22-1

  // Returns NULL if parsing failed.
  FunctionLiteral* ParseProgram(Isolate* isolate, ParseInfo* info);

  FunctionLiteral* ParseLazy(Isolate* isolate, ParseInfo* info);
  FunctionLiteral* DoParseLazy(ParseInfo* info, const AstRawString* raw_name,
                               Utf16CharacterStream* source);

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

  void SetCachedData(ParseInfo* info);

  ScriptCompiler::CompileOptions compile_options() const {
    return compile_options_;
  }
  bool consume_cached_parse_data() const {
    return compile_options_ == ScriptCompiler::kConsumeParserCache &&
           cached_parse_data_ != NULL;
  }
  bool produce_cached_parse_data() const {
    return compile_options_ == ScriptCompiler::kProduceParserCache;
  }

  void ParseModuleItemList(ZoneList<Statement*>* body, bool* ok);
  Statement* ParseModuleItem(bool* ok);
  const AstRawString* ParseModuleSpecifier(bool* ok);
  void ParseImportDeclaration(bool* ok);
  Statement* ParseExportDeclaration(bool* ok);
  Statement* ParseExportDefault(bool* ok);
  void ParseExportClause(ZoneList<const AstRawString*>* export_names,
                         ZoneList<Scanner::Location>* export_locations,
                         ZoneList<const AstRawString*>* local_names,
                         Scanner::Location* reserved_loc, bool* ok);
  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) {}
  };
  ZoneList<const NamedImport*>* ParseNamedImports(int pos, bool* ok);
  Statement* ParseFunctionDeclaration(bool* ok);
  Statement* ParseAsyncFunctionDeclaration(ZoneList<const AstRawString*>* names,
                                           bool default_export, bool* ok);
  Expression* ParseAsyncFunctionExpression(bool* ok);
  Statement* ParseClassDeclaration(ZoneList<const AstRawString*>* names,
                                   bool default_export, bool* ok);
  Statement* ParseNativeDeclaration(bool* ok);
  Block* BuildInitializationBlock(DeclarationParsingResult* parsing_result,
                                  ZoneList<const AstRawString*>* names,
                                  bool* ok);
  void DeclareAndInitializeVariables(
      Block* block, const DeclarationDescriptor* declaration_descriptor,
      const DeclarationParsingResult::Declaration* declaration,
      ZoneList<const AstRawString*>* names, bool* ok);
  ZoneList<const AstRawString*>* DeclareLabel(
      ZoneList<const AstRawString*>* labels, VariableProxy* expr, bool* ok);
  bool ContainsLabel(ZoneList<const AstRawString*>* labels,
                     const AstRawString* label);
  Expression* RewriteReturn(Expression* return_value, int pos);
  Statement* RewriteSwitchStatement(Expression* tag,
                                    SwitchStatement* switch_statement,
                                    ZoneList<CaseClause*>* cases, Scope* scope);

  Statement* DeclareFunction(const AstRawString* variable_name,
                             FunctionLiteral* function, int pos,
                             bool is_generator, bool is_async,
                             ZoneList<const AstRawString*>* names, bool* ok);

  Expression* ParseYieldStarExpression(bool* ok);

  class PatternRewriter final : public AstVisitor<PatternRewriter> {
   public:
    static void DeclareAndInitializeVariables(
        Parser* parser, Block* block,
        const DeclarationDescriptor* declaration_descriptor,
        const DeclarationParsingResult::Declaration* declaration,
        ZoneList<const AstRawString*>* names, bool* ok);

    static void RewriteDestructuringAssignment(Parser* parser,
                                               RewritableExpression* expr,
                                               Scope* Scope);

    static Expression* RewriteDestructuringAssignment(Parser* parser,
                                                      Assignment* assignment,
                                                      Scope* scope);

   private:
    PatternRewriter() {}

#define DECLARE_VISIT(type) void Visit##type(v8::internal::type* node);
    // Visiting functions for AST nodes make this an AstVisitor.
    AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT

    enum PatternContext {
      BINDING,
      INITIALIZER,
      ASSIGNMENT,
      ASSIGNMENT_INITIALIZER
    };

    PatternContext context() const { return context_; }
    void set_context(PatternContext context) { context_ = context; }

    void RecurseIntoSubpattern(AstNode* pattern, Expression* value) {
      Expression* old_value = current_value_;
      current_value_ = value;
      recursion_level_++;
      Visit(pattern);
      recursion_level_--;
      current_value_ = old_value;
    }

    void VisitObjectLiteral(ObjectLiteral* node, Variable** temp_var);
    void VisitArrayLiteral(ArrayLiteral* node, Variable** temp_var);

    bool IsBindingContext() const { return IsBindingContext(context_); }
    bool IsInitializerContext() const { return context_ != ASSIGNMENT; }
    bool IsAssignmentContext() const { return IsAssignmentContext(context_); }
    bool IsAssignmentContext(PatternContext c) const;
    bool IsBindingContext(PatternContext c) const;
    bool IsSubPattern() const { return recursion_level_ > 1; }
    PatternContext SetAssignmentContextIfNeeded(Expression* node);
    PatternContext SetInitializerContextIfNeeded(Expression* node);

    void RewriteParameterScopes(Expression* expr);

    Variable* CreateTempVar(Expression* value = nullptr);

    AstNodeFactory* factory() const { return parser_->factory(); }
    AstValueFactory* ast_value_factory() const {
      return parser_->ast_value_factory();
    }
    Zone* zone() const { return parser_->zone(); }
    Scope* scope() const { return scope_; }

    Scope* scope_;
    Parser* parser_;
    PatternContext context_;
    Expression* pattern_;
    int initializer_position_;
    Block* block_;
    const DeclarationDescriptor* descriptor_;
    ZoneList<const AstRawString*>* names_;
    Expression* current_value_;
    int recursion_level_;
    bool* ok_;

    DEFINE_AST_VISITOR_MEMBERS_WITHOUT_STACKOVERFLOW()
  };

  Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
  Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
  TryStatement* ParseTryStatement(bool* ok);

  // !%_IsJSReceiver(result = iterator.next()) &&
  //     %ThrowIteratorResultNotAnObject(result)
  Expression* BuildIteratorNextResult(Expression* iterator, Variable* result,
                                      int pos);

  Expression* GetIterator(Expression* iterable, int pos);

  // Initialize the components of a for-in / for-of statement.
  Statement* InitializeForEachStatement(ForEachStatement* stmt,
                                        Expression* each, Expression* subject,
                                        Statement* body, int each_keyword_pos);
  Statement* InitializeForOfStatement(ForOfStatement* stmt, Expression* each,
                                      Expression* iterable, Statement* body,
                                      bool finalize,
                                      int next_result_pos = kNoSourcePosition);
  Statement* DesugarLexicalBindingsInForStatement(
      Scope* inner_scope, VariableMode mode,
      ZoneList<const AstRawString*>* names, ForStatement* loop, Statement* init,
      Expression* cond, Statement* next, Statement* body, bool* ok);

  void DesugarAsyncFunctionBody(Scope* scope, ZoneList<Statement*>* body,
                                FunctionKind kind, FunctionBodyType type,
                                bool accept_IN, int pos, bool* ok);

  Expression* RewriteDoExpression(Block* body, int pos, bool* ok);

  FunctionLiteral* ParseFunctionLiteral(
      const AstRawString* name, Scanner::Location function_name_location,
      FunctionNameValidity function_name_validity, FunctionKind kind,
      int function_token_position, FunctionLiteral::FunctionType type,
      LanguageMode language_mode, bool* ok);

  Expression* InstallHomeObject(Expression* function_literal,
                                Expression* home_object);
  FunctionLiteral* SynthesizeClassFieldInitializer(int count);
  FunctionLiteral* InsertClassFieldInitializer(FunctionLiteral* constructor);

  Expression* ParseClassLiteral(const AstRawString* name,
                                Scanner::Location class_name_location,
                                bool name_is_strict_reserved, int pos,
                                bool* ok);

  // Get odd-ball literals.
  Literal* GetLiteralUndefined(int position);

  // Check if the scope has conflicting var/let declarations from different
  // scopes. This covers for example
  //
  // function f() { { { var x; } let x; } }
  // function g() { { var x; let x; } }
  //
  // The var declarations are hoisted to the function scope, but originate from
  // a scope where the name has also been let bound or the var declaration is
  // hoisted over such a scope.
  void CheckConflictingVarDeclarations(Scope* scope, bool* ok);

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

  VariableProxy* NewUnresolved(const AstRawString* name, int begin_pos,
                               int end_pos = kNoSourcePosition,
                               VariableKind kind = NORMAL_VARIABLE);
  VariableProxy* NewUnresolved(const AstRawString* name);
  Variable* Declare(Declaration* declaration,
                    DeclarationDescriptor::Kind declaration_kind,
                    VariableMode mode, InitializationFlag init, bool* ok,
                    Scope* declaration_scope = nullptr);
  Declaration* DeclareVariable(const AstRawString* name, VariableMode mode,
                               int pos, bool* ok);
  Declaration* DeclareVariable(const AstRawString* name, VariableMode mode,
                               InitializationFlag init, int pos, bool* ok);

  bool TargetStackContainsLabel(const AstRawString* label);
  BreakableStatement* LookupBreakTarget(const AstRawString* label, bool* ok);
  IterationStatement* LookupContinueTarget(const AstRawString* label, bool* ok);

  Statement* BuildAssertIsCoercible(Variable* var);

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

  // Skip over a lazy function, either using cached data if we have it, or
  // by parsing the function with PreParser. Consumes the ending }.
  // If may_abort == true, the (pre-)parser may decide to abort skipping
  // in order to force the function to be eagerly parsed, after all.
  LazyParsingResult SkipLazyFunctionBody(int* materialized_literal_count,
                                         int* expected_property_count,
                                         bool may_abort, bool* ok);

  PreParser::PreParseResult ParseLazyFunctionBodyWithPreParser(
      SingletonLogger* logger, bool may_abort);

  Block* BuildParameterInitializationBlock(
      const ParserFormalParameters& parameters, bool* ok);
  Block* BuildRejectPromiseOnException(Block* block, bool* ok);

  // Consumes the ending }.
  ZoneList<Statement*>* ParseEagerFunctionBody(
      const AstRawString* function_name, int pos,
      const ParserFormalParameters& parameters, FunctionKind kind,
      FunctionLiteral::FunctionType function_type, bool* ok);

  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 ZoneList<Expression*>* cooked() const { return &cooked_; }
    const ZoneList<Expression*>* raw() const { return &raw_; }
    const ZoneList<Expression*>* expressions() const { return &expressions_; }
    int position() const { return pos_; }

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

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

   private:
    ZoneList<Expression*> cooked_;
    ZoneList<Expression*> raw_;
    ZoneList<Expression*> expressions_;
    int pos_;
  };

  typedef TemplateLiteral* TemplateLiteralState;

  TemplateLiteralState OpenTemplateLiteral(int pos);
  void AddTemplateSpan(TemplateLiteralState* state, bool tail);
  void AddTemplateExpression(TemplateLiteralState* state,
                             Expression* expression);
  Expression* CloseTemplateLiteral(TemplateLiteralState* state, int start,
                                   Expression* tag);
  uint32_t ComputeTemplateLiteralHash(const TemplateLiteral* lit);

  void ParseAsyncArrowSingleExpressionBody(ZoneList<Statement*>* body,
                                           bool accept_IN,
                                           int pos, bool* ok) {
    DesugarAsyncFunctionBody(scope(), body, kAsyncArrowFunction,
                             FunctionBodyType::kSingleExpression, accept_IN,
                             pos, ok);
  }

  ZoneList<Expression*>* PrepareSpreadArguments(ZoneList<Expression*>* list);
  Expression* SpreadCall(Expression* function, ZoneList<Expression*>* args,
                         int pos);
  Expression* SpreadCallNew(Expression* function, ZoneList<Expression*>* args,
                            int pos);
  Expression* CallClassFieldInitializer(Scope* scope, Expression* this_expr);
  Expression* RewriteSuperCall(Expression* call_expression);

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

  V8_INLINE void MarkCollectedTailCallExpressions();
  V8_INLINE void MarkTailPosition(Expression* expression);

  // Rewrite all DestructuringAssignments in the current FunctionState.
  V8_INLINE void RewriteDestructuringAssignments();

  V8_INLINE Expression* RewriteExponentiation(Expression* left,
                                              Expression* right, int pos);
  V8_INLINE Expression* RewriteAssignExponentiation(Expression* left,
                                                    Expression* right, int pos);

  friend class NonPatternRewriter;
  V8_INLINE Expression* RewriteSpreads(ArrayLiteral* lit);

  // Rewrite expressions that are not used as patterns
  V8_INLINE void RewriteNonPattern(bool* ok);

  V8_INLINE void QueueDestructuringAssignmentForRewriting(
      Expression* assignment);
  V8_INLINE void QueueNonPatternForRewriting(Expression* expr, bool* ok);

  friend class InitializerRewriter;
  void RewriteParameterInitializer(Expression* expr, Scope* scope);

  Expression* BuildCreateJSGeneratorObject(int pos, FunctionKind kind);
  Expression* BuildResolvePromise(Expression* value, int pos);
  Expression* BuildRejectPromise(Expression* value, int pos);
  VariableProxy* BuildDotPromise();
  VariableProxy* BuildDotDebugIsActive();

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

  void FinalizeIteratorUse(Variable* completion, Expression* condition,
                           Variable* iter, Block* iterator_use, Block* result);

  Statement* FinalizeForOfStatement(ForOfStatement* loop, Variable* completion,
                                    int pos);
  void BuildIteratorClose(ZoneList<Statement*>* statements, Variable* iterator,
                          Variable* input, Variable* output);
  void BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements,
                                       Variable* iterator,
                                       Expression* completion);
  Statement* CheckCallable(Variable* var, Expression* error, int pos);

  V8_INLINE Expression* RewriteAwaitExpression(Expression* value, int pos);

  Expression* RewriteYieldStar(Expression* generator, Expression* expression,
                               int pos);

  void ParseArrowFunctionFormalParameters(ParserFormalParameters* parameters,
                                          Expression* params, int end_pos,
                                          bool* ok);
  void SetFunctionName(Expression* value, const AstRawString* name);

  // Helper functions for recursive descent.
  V8_INLINE bool IsEval(const AstRawString* identifier) const {
    return identifier == ast_value_factory()->eval_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);
  }

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

  V8_INLINE bool IsFutureStrictReserved(const AstRawString* identifier) const {
    return scanner()->IdentifierIsFutureStrictReserved(identifier);
  }

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

  // 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) {
    DCHECK_NOT_NULL(expression);
    VariableProxy* operand = expression->AsVariableProxy();
    return operand != nullptr && !operand->is_this();
  }

  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 IsPrototype(const AstRawString* identifier) const {
    return identifier == ast_value_factory()->prototype_string();
  }

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

  V8_INLINE bool IsDirectEvalCall(Expression* expression) const {
    if (!expression->IsCall()) return false;
    expression = expression->AsCall()->expression();
    return IsIdentifier(expression) && IsEval(AsIdentifier(expression));
  }

  V8_INLINE static bool IsBoilerplateProperty(
      ObjectLiteral::Property* property) {
    return ObjectLiteral::IsBoilerplateProperty(property);
  }

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

  V8_INLINE bool IsUseStrictDirective(Statement* statement) const {
    return IsStringLiteral(statement, ast_value_factory()->use_strict_string());
  }

  V8_INLINE bool IsUseAsmDirective(Statement* statement) const {
    return IsStringLiteral(statement, ast_value_factory()->use_asm_string());
  }

  // 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->raw_value()->IsString()) return false;
    return arg == nullptr || literal->raw_value()->AsString() == arg;
  }

  V8_INLINE static Expression* GetPropertyValue(LiteralProperty* property) {
    return property->value();
  }

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

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

  V8_INLINE void PushVariableName(const AstRawString* id) {
    DCHECK_NOT_NULL(fni_);
    fni_->PushVariableName(id);
  }

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

  V8_INLINE void PushEnclosingName(const AstRawString* name) {
    DCHECK_NOT_NULL(fni_);
    fni_->PushEnclosingName(name);
  }

  V8_INLINE void InferFunctionName(FunctionLiteral* func_to_infer) {
    fni_->AddFunction(func_to_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(left != NULL);
    if (left->IsProperty() && right->IsFunctionLiteral()) {
      right->AsFunctionLiteral()->set_pretenure();
    }
  }

  // Determine if the expression is a variable proxy and mark it as being used
  // in an assignment or with a increment/decrement operator.
  V8_INLINE static Expression* MarkExpressionAsAssigned(
      Expression* expression) {
    VariableProxy* proxy =
        expression != NULL ? expression->AsVariableProxy() : NULL;
    if (proxy != NULL) proxy->set_is_assigned();
    return expression;
  }

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

  // Rewrites the following types of unary expressions:
  // not <literal> -> true / false
  // + <numeric literal> -> <numeric literal>
  // - <numeric literal> -> <numeric literal with value negated>
  // ! <literal> -> true / false
  // The following rewriting rules enable the collection of type feedback
  // without any special stub and the multiplication is removed later in
  // Crankshaft's canonicalization pass.
  // + foo -> foo * 1
  // - foo -> foo * (-1)
  // ~ foo -> foo ^(~0)
  Expression* BuildUnaryExpression(Expression* expression, Token::Value op,
                                   int pos);

  Expression* BuildIteratorResult(Expression* value, bool done);

  // Generate AST node that throws a ReferenceError with the given type.
  V8_INLINE Expression* NewThrowReferenceError(
      MessageTemplate::Template 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::Template 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::Template message,
                                          const AstRawString* arg, int pos) {
    return NewThrowError(Runtime::kNewTypeError, message, arg, pos);
  }

  // Reporting errors.
  V8_INLINE void ReportMessageAt(Scanner::Location source_location,
                                 MessageTemplate::Template message,
                                 const char* arg = NULL,
                                 ParseErrorType error_type = kSyntaxError) {
    if (stack_overflow()) {
      // Suppress the error message (syntax error or such) in the presence of a
      // stack overflow. The isolate allows only one pending exception at at
      // time
      // and we want to report the stack overflow later.
      return;
    }
    pending_error_handler_.ReportMessageAt(source_location.beg_pos,
                                           source_location.end_pos, message,
                                           arg, error_type);
  }

  V8_INLINE void ReportMessageAt(Scanner::Location source_location,
                                 MessageTemplate::Template message,
                                 const AstRawString* arg,
                                 ParseErrorType error_type = kSyntaxError) {
    if (stack_overflow()) {
      // Suppress the error message (syntax error or such) in the presence of a
      // stack overflow. The isolate allows only one pending exception at at
      // time
      // and we want to report the stack overflow later.
      return;
    }
    pending_error_handler_.ReportMessageAt(source_location.beg_pos,
                                           source_location.end_pos, message,
                                           arg, error_type);
  }

  // "null" return type creators.
  V8_INLINE static const AstRawString* EmptyIdentifier() { return nullptr; }
  V8_INLINE static bool IsEmptyIdentifier(const AstRawString* name) {
    return name == nullptr;
  }
  V8_INLINE static Expression* EmptyExpression() { return nullptr; }
  V8_INLINE static Literal* EmptyLiteral() { return nullptr; }
  V8_INLINE static ObjectLiteralProperty* EmptyObjectLiteralProperty() {
    return nullptr;
  }
  V8_INLINE static ClassLiteralProperty* EmptyClassLiteralProperty() {
    return nullptr;
  }
  V8_INLINE static FunctionLiteral* EmptyFunctionLiteral() { return nullptr; }
  V8_INLINE static Block* NullBlock() { return nullptr; }

  V8_INLINE static bool IsEmptyExpression(Expression* expr) {
    return expr == nullptr;
  }

  // Used in error return values.
  V8_INLINE static ZoneList<Expression*>* NullExpressionList() {
    return nullptr;
  }
  V8_INLINE static bool IsNullExpressionList(ZoneList<Expression*>* exprs) {
    return exprs == nullptr;
  }
  V8_INLINE static ZoneList<Statement*>* NullStatementList() { return nullptr; }
  V8_INLINE static bool IsNullStatementList(ZoneList<Statement*>* stmts) {
    return stmts == nullptr;
  }
  V8_INLINE static Statement* NullStatement() { return nullptr; }
  V8_INLINE bool IsNullStatement(Statement* stmt) { return stmt == nullptr; }
  V8_INLINE bool IsEmptyStatement(Statement* stmt) {
    DCHECK_NOT_NULL(stmt);
    return stmt->IsEmpty();
  }

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

  // Odd-ball literal creators.
  V8_INLINE Literal* GetLiteralTheHole(int position) {
    return factory()->NewTheHoleLiteral(kNoSourcePosition);
  }

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

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

  V8_INLINE Expression* ThisExpression(int pos = kNoSourcePosition) {
    return NewUnresolved(ast_value_factory()->this_string(), pos, pos + 4,
                         THIS_VARIABLE);
  }

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

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

  V8_INLINE Expression* ExpressionFromIdentifier(
      const AstRawString* name, int start_position, int end_position,
      InferName infer = InferName::kYes) {
    if (infer == InferName::kYes) {
      fni_->PushVariableName(name);
    }
    return NewUnresolved(name, start_position, end_position);
  }

  V8_INLINE Expression* ExpressionFromString(int pos) {
    const AstRawString* symbol = GetSymbol();
    fni_->PushLiteralName(symbol);
    return factory()->NewStringLiteral(symbol, pos);
  }

  V8_INLINE ZoneList<Expression*>* NewExpressionList(int size) const {
    return new (zone()) ZoneList<Expression*>(size, zone());
  }
  V8_INLINE ZoneList<ObjectLiteral::Property*>* NewPropertyList(
      int size) const {
    return new (zone()) ZoneList<ObjectLiteral::Property*>(size, zone());
  }
  V8_INLINE ZoneList<ClassLiteral::Property*>* NewClassPropertyList(
      int size) const {
    return new (zone()) ZoneList<ClassLiteral::Property*>(size, zone());
  }
  V8_INLINE ZoneList<Statement*>* NewStatementList(int size) const {
    return new (zone()) ZoneList<Statement*>(size, zone());
  }
  V8_INLINE ZoneList<CaseClause*>* NewCaseClauseList(int size) const {
    return new (zone()) ZoneList<CaseClause*>(size, zone());
  }

  V8_INLINE Block* NewBlock(ZoneList<const AstRawString*>* labels, int capacity,
                            bool ignore_completion_value, int pos) {
    return factory()->NewBlock(labels, capacity, ignore_completion_value, pos);
  }

  V8_INLINE Expression* NewV8Intrinsic(const AstRawString* name,
                                       ZoneList<Expression*>* args, int pos,
                                       bool* ok);

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

  V8_INLINE void AddParameterInitializationBlock(
      const ParserFormalParameters& parameters, ZoneList<Statement*>* body,
      bool is_async, bool* ok) {
    if (parameters.is_simple) return;
    auto* init_block = BuildParameterInitializationBlock(parameters, ok);
    if (!*ok) return;
    if (is_async) {
      init_block = BuildRejectPromiseOnException(init_block, ok);
      if (!*ok) return;
    }
    if (init_block != nullptr) body->Add(init_block, zone());
  }

  V8_INLINE void AddFormalParameter(ParserFormalParameters* parameters,
                                    Expression* pattern,
                                    Expression* initializer,
                                    int initializer_end_position,
                                    bool is_rest) {
    bool is_simple = pattern->IsVariableProxy() && initializer == nullptr;
    const AstRawString* name = is_simple
                                   ? pattern->AsVariableProxy()->raw_name()
                                   : ast_value_factory()->empty_string();
    parameters->params.Add(
        ParserFormalParameters::Parameter(name, pattern, initializer,
                                          initializer_end_position, is_rest),
        parameters->scope->zone());
  }

  V8_INLINE void DeclareFormalParameter(
      DeclarationScope* scope,
      const ParserFormalParameters::Parameter& parameter) {
    bool is_duplicate = false;
    bool is_simple = classifier()->is_simple_parameter_list();
    auto name = is_simple || parameter.is_rest
                    ? parameter.name
                    : ast_value_factory()->empty_string();
    auto mode = is_simple || parameter.is_rest ? VAR : TEMPORARY;
    if (!is_simple) scope->SetHasNonSimpleParameters();
    bool is_optional = parameter.initializer != nullptr;
    Variable* var =
        scope->DeclareParameter(name, mode, is_optional, parameter.is_rest,
                                &is_duplicate, ast_value_factory());
    if (is_duplicate) {
      classifier()->RecordDuplicateFormalParameterError(scanner()->location());
    }
    if (is_sloppy(scope->language_mode())) {
      // TODO(sigurds) Mark every parameter as maybe assigned. This is a
      // conservative approximation necessary to account for parameters
      // that are assigned via the arguments array.
      var->set_maybe_assigned();
    }
  }

  void ParseArrowFunctionFormalParameterList(
      ParserFormalParameters* parameters, Expression* params,
      const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
      const Scope::Snapshot& scope_snapshot, bool* ok);

  void ReindexLiterals(const ParserFormalParameters& parameters);

  V8_INLINE Expression* NoTemplateTag() { return NULL; }
  V8_INLINE static bool IsTaggedTemplate(const Expression* tag) {
    return tag != NULL;
  }

  V8_INLINE void MaterializeUnspreadArgumentsLiterals(int count) {}

  Expression* ExpressionListToExpression(ZoneList<Expression*>* args);

  void AddAccessorPrefixToFunctionName(bool is_get, FunctionLiteral* function,
                                       const AstRawString* name);

  void SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
                                       const AstRawString* name);

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

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

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

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

  // Parser's private field members.

  Scanner scanner_;
  PreParser* reusable_preparser_;
  Scope* original_scope_;  // for ES5 function declarations in sloppy eval

  friend class ParserTarget;
  friend class ParserTargetScope;
  ParserTarget* target_stack_;  // for break, continue statements

  ScriptCompiler::CompileOptions compile_options_;
  ParseData* cached_parse_data_;

  PendingCompilationErrorHandler pending_error_handler_;

  // Other information which will be stored in Parser and moved to Isolate after
  // parsing.
  int use_counts_[v8::Isolate::kUseCounterFeatureCount];
  int total_preparse_skipped_;
  HistogramTimer* pre_parse_timer_;

  bool parsing_on_main_thread_;

#ifdef DEBUG
  void Print(AstNode* node);
#endif  // DEBUG
};

}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_PARSER_H_
