diff --git a/src/parsing/OWNERS b/src/parsing/OWNERS
new file mode 100644
index 0000000..a5daeb3
--- /dev/null
+++ b/src/parsing/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+adamk@chromium.org
+littledan@chromium.org
+marja@chromium.org
+rossberg@chromium.org
+
diff --git a/src/parsing/expression-classifier.h b/src/parsing/expression-classifier.h
new file mode 100644
index 0000000..96ccf87
--- /dev/null
+++ b/src/parsing/expression-classifier.h
@@ -0,0 +1,356 @@
+// Copyright 2015 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_EXPRESSION_CLASSIFIER_H
+#define V8_PARSING_EXPRESSION_CLASSIFIER_H
+
+#include "src/messages.h"
+#include "src/parsing/scanner.h"
+#include "src/parsing/token.h"
+
+namespace v8 {
+namespace internal {
+
+
+class ExpressionClassifier {
+ public:
+  struct Error {
+    Error()
+        : location(Scanner::Location::invalid()),
+          message(MessageTemplate::kNone),
+          type(kSyntaxError),
+          arg(nullptr) {}
+
+    Scanner::Location location;
+    MessageTemplate::Template message : 30;
+    ParseErrorType type : 2;
+    const char* arg;
+  };
+
+  enum TargetProduction {
+    ExpressionProduction = 1 << 0,
+    FormalParameterInitializerProduction = 1 << 1,
+    BindingPatternProduction = 1 << 2,
+    AssignmentPatternProduction = 1 << 3,
+    DistinctFormalParametersProduction = 1 << 4,
+    StrictModeFormalParametersProduction = 1 << 5,
+    StrongModeFormalParametersProduction = 1 << 6,
+    ArrowFormalParametersProduction = 1 << 7,
+    LetPatternProduction = 1 << 8,
+    CoverInitializedNameProduction = 1 << 9,
+
+    ExpressionProductions =
+        (ExpressionProduction | FormalParameterInitializerProduction),
+    PatternProductions = (BindingPatternProduction |
+                          AssignmentPatternProduction | LetPatternProduction),
+    FormalParametersProductions = (DistinctFormalParametersProduction |
+                                   StrictModeFormalParametersProduction |
+                                   StrongModeFormalParametersProduction),
+    StandardProductions = ExpressionProductions | PatternProductions,
+    AllProductions =
+        (StandardProductions | FormalParametersProductions |
+         ArrowFormalParametersProduction | CoverInitializedNameProduction)
+  };
+
+  enum FunctionProperties { NonSimpleParameter = 1 << 0 };
+
+  ExpressionClassifier()
+      : invalid_productions_(0),
+        function_properties_(0),
+        duplicate_finder_(nullptr) {}
+
+  explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
+      : invalid_productions_(0),
+        function_properties_(0),
+        duplicate_finder_(duplicate_finder) {}
+
+  bool is_valid(unsigned productions) const {
+    return (invalid_productions_ & productions) == 0;
+  }
+
+  DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
+
+  bool is_valid_expression() const { return is_valid(ExpressionProduction); }
+
+  bool is_valid_formal_parameter_initializer() const {
+    return is_valid(FormalParameterInitializerProduction);
+  }
+
+  bool is_valid_binding_pattern() const {
+    return is_valid(BindingPatternProduction);
+  }
+
+  bool is_valid_assignment_pattern() const {
+    return is_valid(AssignmentPatternProduction);
+  }
+
+  bool is_valid_arrow_formal_parameters() const {
+    return is_valid(ArrowFormalParametersProduction);
+  }
+
+  bool is_valid_formal_parameter_list_without_duplicates() const {
+    return is_valid(DistinctFormalParametersProduction);
+  }
+
+  // Note: callers should also check
+  // is_valid_formal_parameter_list_without_duplicates().
+  bool is_valid_strict_mode_formal_parameters() const {
+    return is_valid(StrictModeFormalParametersProduction);
+  }
+
+  // Note: callers should also check is_valid_strict_mode_formal_parameters()
+  // and is_valid_formal_parameter_list_without_duplicates().
+  bool is_valid_strong_mode_formal_parameters() const {
+    return is_valid(StrongModeFormalParametersProduction);
+  }
+
+  bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
+
+  const Error& expression_error() const { return expression_error_; }
+
+  const Error& formal_parameter_initializer_error() const {
+    return formal_parameter_initializer_error_;
+  }
+
+  const Error& binding_pattern_error() const { return binding_pattern_error_; }
+
+  const Error& assignment_pattern_error() const {
+    return assignment_pattern_error_;
+  }
+
+  const Error& arrow_formal_parameters_error() const {
+    return arrow_formal_parameters_error_;
+  }
+
+  const Error& duplicate_formal_parameter_error() const {
+    return duplicate_formal_parameter_error_;
+  }
+
+  const Error& strict_mode_formal_parameter_error() const {
+    return strict_mode_formal_parameter_error_;
+  }
+
+  const Error& strong_mode_formal_parameter_error() const {
+    return strong_mode_formal_parameter_error_;
+  }
+
+  const Error& let_pattern_error() const { return let_pattern_error_; }
+
+  bool has_cover_initialized_name() const {
+    return !is_valid(CoverInitializedNameProduction);
+  }
+  const Error& cover_initialized_name_error() const {
+    return cover_initialized_name_error_;
+  }
+
+  bool is_simple_parameter_list() const {
+    return !(function_properties_ & NonSimpleParameter);
+  }
+
+  void RecordNonSimpleParameter() {
+    function_properties_ |= NonSimpleParameter;
+  }
+
+  void RecordExpressionError(const Scanner::Location& loc,
+                             MessageTemplate::Template message,
+                             const char* arg = nullptr) {
+    if (!is_valid_expression()) return;
+    invalid_productions_ |= ExpressionProduction;
+    expression_error_.location = loc;
+    expression_error_.message = message;
+    expression_error_.arg = arg;
+  }
+
+  void RecordExpressionError(const Scanner::Location& loc,
+                             MessageTemplate::Template message,
+                             ParseErrorType type, const char* arg = nullptr) {
+    if (!is_valid_expression()) return;
+    invalid_productions_ |= ExpressionProduction;
+    expression_error_.location = loc;
+    expression_error_.message = message;
+    expression_error_.arg = arg;
+    expression_error_.type = type;
+  }
+
+  void RecordFormalParameterInitializerError(const Scanner::Location& loc,
+                                             MessageTemplate::Template message,
+                                             const char* arg = nullptr) {
+    if (!is_valid_formal_parameter_initializer()) return;
+    invalid_productions_ |= FormalParameterInitializerProduction;
+    formal_parameter_initializer_error_.location = loc;
+    formal_parameter_initializer_error_.message = message;
+    formal_parameter_initializer_error_.arg = arg;
+  }
+
+  void RecordBindingPatternError(const Scanner::Location& loc,
+                                 MessageTemplate::Template message,
+                                 const char* arg = nullptr) {
+    if (!is_valid_binding_pattern()) return;
+    invalid_productions_ |= BindingPatternProduction;
+    binding_pattern_error_.location = loc;
+    binding_pattern_error_.message = message;
+    binding_pattern_error_.arg = arg;
+  }
+
+  void RecordAssignmentPatternError(const Scanner::Location& loc,
+                                    MessageTemplate::Template message,
+                                    const char* arg = nullptr) {
+    if (!is_valid_assignment_pattern()) return;
+    invalid_productions_ |= AssignmentPatternProduction;
+    assignment_pattern_error_.location = loc;
+    assignment_pattern_error_.message = message;
+    assignment_pattern_error_.arg = arg;
+  }
+
+  void RecordPatternError(const Scanner::Location& loc,
+                          MessageTemplate::Template message,
+                          const char* arg = nullptr) {
+    RecordBindingPatternError(loc, message, arg);
+    RecordAssignmentPatternError(loc, message, arg);
+  }
+
+  void RecordArrowFormalParametersError(const Scanner::Location& loc,
+                                        MessageTemplate::Template message,
+                                        const char* arg = nullptr) {
+    if (!is_valid_arrow_formal_parameters()) return;
+    invalid_productions_ |= ArrowFormalParametersProduction;
+    arrow_formal_parameters_error_.location = loc;
+    arrow_formal_parameters_error_.message = message;
+    arrow_formal_parameters_error_.arg = arg;
+  }
+
+  void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
+    if (!is_valid_formal_parameter_list_without_duplicates()) return;
+    invalid_productions_ |= DistinctFormalParametersProduction;
+    duplicate_formal_parameter_error_.location = loc;
+    duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
+    duplicate_formal_parameter_error_.arg = nullptr;
+  }
+
+  // Record a binding that would be invalid in strict mode.  Confusingly this
+  // is not the same as StrictFormalParameterList, which simply forbids
+  // duplicate bindings.
+  void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
+                                            MessageTemplate::Template message,
+                                            const char* arg = nullptr) {
+    if (!is_valid_strict_mode_formal_parameters()) return;
+    invalid_productions_ |= StrictModeFormalParametersProduction;
+    strict_mode_formal_parameter_error_.location = loc;
+    strict_mode_formal_parameter_error_.message = message;
+    strict_mode_formal_parameter_error_.arg = arg;
+  }
+
+  void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
+                                            MessageTemplate::Template message,
+                                            const char* arg = nullptr) {
+    if (!is_valid_strong_mode_formal_parameters()) return;
+    invalid_productions_ |= StrongModeFormalParametersProduction;
+    strong_mode_formal_parameter_error_.location = loc;
+    strong_mode_formal_parameter_error_.message = message;
+    strong_mode_formal_parameter_error_.arg = arg;
+  }
+
+  void RecordLetPatternError(const Scanner::Location& loc,
+                             MessageTemplate::Template message,
+                             const char* arg = nullptr) {
+    if (!is_valid_let_pattern()) return;
+    invalid_productions_ |= LetPatternProduction;
+    let_pattern_error_.location = loc;
+    let_pattern_error_.message = message;
+    let_pattern_error_.arg = arg;
+  }
+
+  void RecordCoverInitializedNameError(const Scanner::Location& loc,
+                                       MessageTemplate::Template message,
+                                       const char* arg = nullptr) {
+    if (has_cover_initialized_name()) return;
+    invalid_productions_ |= CoverInitializedNameProduction;
+    cover_initialized_name_error_.location = loc;
+    cover_initialized_name_error_.message = message;
+    cover_initialized_name_error_.arg = arg;
+  }
+
+  void ForgiveCoverInitializedNameError() {
+    invalid_productions_ &= ~CoverInitializedNameProduction;
+    cover_initialized_name_error_ = Error();
+  }
+
+  void ForgiveAssignmentPatternError() {
+    invalid_productions_ &= ~AssignmentPatternProduction;
+    assignment_pattern_error_ = Error();
+  }
+
+  void Accumulate(const ExpressionClassifier& inner,
+                  unsigned productions = StandardProductions) {
+    // Propagate errors from inner, but don't overwrite already recorded
+    // errors.
+    unsigned non_arrow_inner_invalid_productions =
+        inner.invalid_productions_ & ~ArrowFormalParametersProduction;
+    if (non_arrow_inner_invalid_productions == 0) return;
+    unsigned non_arrow_productions =
+        productions & ~ArrowFormalParametersProduction;
+    unsigned errors =
+        non_arrow_productions & non_arrow_inner_invalid_productions;
+    errors &= ~invalid_productions_;
+    if (errors != 0) {
+      invalid_productions_ |= errors;
+      if (errors & ExpressionProduction)
+        expression_error_ = inner.expression_error_;
+      if (errors & FormalParameterInitializerProduction)
+        formal_parameter_initializer_error_ =
+            inner.formal_parameter_initializer_error_;
+      if (errors & BindingPatternProduction)
+        binding_pattern_error_ = inner.binding_pattern_error_;
+      if (errors & AssignmentPatternProduction)
+        assignment_pattern_error_ = inner.assignment_pattern_error_;
+      if (errors & DistinctFormalParametersProduction)
+        duplicate_formal_parameter_error_ =
+            inner.duplicate_formal_parameter_error_;
+      if (errors & StrictModeFormalParametersProduction)
+        strict_mode_formal_parameter_error_ =
+            inner.strict_mode_formal_parameter_error_;
+      if (errors & StrongModeFormalParametersProduction)
+        strong_mode_formal_parameter_error_ =
+            inner.strong_mode_formal_parameter_error_;
+      if (errors & LetPatternProduction)
+        let_pattern_error_ = inner.let_pattern_error_;
+      if (errors & CoverInitializedNameProduction)
+        cover_initialized_name_error_ = inner.cover_initialized_name_error_;
+    }
+
+    // As an exception to the above, the result continues to be a valid arrow
+    // formal parameters if the inner expression is a valid binding pattern.
+    if (productions & ArrowFormalParametersProduction &&
+        is_valid_arrow_formal_parameters()) {
+      // Also copy function properties if expecting an arrow function
+      // parameter.
+      function_properties_ |= inner.function_properties_;
+
+      if (!inner.is_valid_binding_pattern()) {
+        invalid_productions_ |= ArrowFormalParametersProduction;
+        arrow_formal_parameters_error_ = inner.binding_pattern_error_;
+      }
+    }
+  }
+
+ private:
+  unsigned invalid_productions_;
+  unsigned function_properties_;
+  Error expression_error_;
+  Error formal_parameter_initializer_error_;
+  Error binding_pattern_error_;
+  Error assignment_pattern_error_;
+  Error arrow_formal_parameters_error_;
+  Error duplicate_formal_parameter_error_;
+  Error strict_mode_formal_parameter_error_;
+  Error strong_mode_formal_parameter_error_;
+  Error let_pattern_error_;
+  Error cover_initialized_name_error_;
+  DuplicateFinder* duplicate_finder_;
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_EXPRESSION_CLASSIFIER_H
diff --git a/src/parsing/func-name-inferrer.cc b/src/parsing/func-name-inferrer.cc
new file mode 100644
index 0000000..12013af
--- /dev/null
+++ b/src/parsing/func-name-inferrer.cc
@@ -0,0 +1,85 @@
+// Copyright 2011 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.
+
+#include "src/parsing/func-name-inferrer.h"
+
+#include "src/ast/ast.h"
+#include "src/ast/ast-value-factory.h"
+#include "src/list-inl.h"
+
+namespace v8 {
+namespace internal {
+
+FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory,
+                                   Zone* zone)
+    : ast_value_factory_(ast_value_factory),
+      entries_stack_(10, zone),
+      names_stack_(5, zone),
+      funcs_to_infer_(4, zone),
+      zone_(zone) {
+}
+
+
+void FuncNameInferrer::PushEnclosingName(const AstRawString* name) {
+  // Enclosing name is a name of a constructor function. To check
+  // that it is really a constructor, we check that it is not empty
+  // and starts with a capital letter.
+  if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) {
+    names_stack_.Add(Name(name, kEnclosingConstructorName), zone());
+  }
+}
+
+
+void FuncNameInferrer::PushLiteralName(const AstRawString* name) {
+  if (IsOpen() && name != ast_value_factory_->prototype_string()) {
+    names_stack_.Add(Name(name, kLiteralName), zone());
+  }
+}
+
+
+void FuncNameInferrer::PushVariableName(const AstRawString* name) {
+  if (IsOpen() && name != ast_value_factory_->dot_result_string()) {
+    names_stack_.Add(Name(name, kVariableName), zone());
+  }
+}
+
+
+const AstString* FuncNameInferrer::MakeNameFromStack() {
+  return MakeNameFromStackHelper(0, ast_value_factory_->empty_string());
+}
+
+const AstString* FuncNameInferrer::MakeNameFromStackHelper(
+    int pos, const AstString* prev) {
+  if (pos >= names_stack_.length()) return prev;
+  if (pos < names_stack_.length() - 1 &&
+      names_stack_.at(pos).type == kVariableName &&
+      names_stack_.at(pos + 1).type == kVariableName) {
+    // Skip consecutive variable declarations.
+    return MakeNameFromStackHelper(pos + 1, prev);
+  } else {
+    if (prev->length() > 0) {
+      const AstRawString* name = names_stack_.at(pos).name;
+      if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
+      const AstConsString* curr = ast_value_factory_->NewConsString(
+          ast_value_factory_->dot_string(), name);
+      curr = ast_value_factory_->NewConsString(prev, curr);
+      return MakeNameFromStackHelper(pos + 1, curr);
+    } else {
+      return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
+    }
+  }
+}
+
+
+void FuncNameInferrer::InferFunctionsNames() {
+  const AstString* func_name = MakeNameFromStack();
+  for (int i = 0; i < funcs_to_infer_.length(); ++i) {
+    funcs_to_infer_[i]->set_raw_inferred_name(func_name);
+  }
+  funcs_to_infer_.Rewind(0);
+}
+
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/func-name-inferrer.h b/src/parsing/func-name-inferrer.h
new file mode 100644
index 0000000..ba38ffe
--- /dev/null
+++ b/src/parsing/func-name-inferrer.h
@@ -0,0 +1,127 @@
+// Copyright 2006-2009 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_FUNC_NAME_INFERRER_H_
+#define V8_PARSING_FUNC_NAME_INFERRER_H_
+
+#include "src/handles.h"
+#include "src/zone.h"
+
+namespace v8 {
+namespace internal {
+
+class AstRawString;
+class AstString;
+class AstValueFactory;
+class FunctionLiteral;
+
+// FuncNameInferrer is a stateful class that is used to perform name
+// inference for anonymous functions during static analysis of source code.
+// Inference is performed in cases when an anonymous function is assigned
+// to a variable or a property (see test-func-name-inference.cc for examples.)
+//
+// The basic idea is that during parsing of LHSs of certain expressions
+// (assignments, declarations, object literals) we collect name strings,
+// and during parsing of the RHS, a function literal can be collected. After
+// parsing the RHS we can infer a name for function literals that do not have
+// a name.
+class FuncNameInferrer : public ZoneObject {
+ public:
+  FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
+
+  // To enter function name inference state, put a FuncNameInferrer::State
+  // on the stack.
+  class State {
+   public:
+    explicit State(FuncNameInferrer* fni) : fni_(fni) {
+      if (fni_ != nullptr) fni_->Enter();
+    }
+    ~State() {
+      if (fni_ != nullptr) fni_->Leave();
+    }
+
+   private:
+    FuncNameInferrer* fni_;
+
+    DISALLOW_COPY_AND_ASSIGN(State);
+  };
+
+  // Returns whether we have entered name collection state.
+  bool IsOpen() const { return !entries_stack_.is_empty(); }
+
+  // Pushes an enclosing the name of enclosing function onto names stack.
+  void PushEnclosingName(const AstRawString* name);
+
+  // Pushes an encountered name onto names stack when in collection state.
+  void PushLiteralName(const AstRawString* name);
+
+  void PushVariableName(const AstRawString* name);
+
+  // Adds a function to infer name for.
+  void AddFunction(FunctionLiteral* func_to_infer) {
+    if (IsOpen()) {
+      funcs_to_infer_.Add(func_to_infer, zone());
+    }
+  }
+
+  void RemoveLastFunction() {
+    if (IsOpen() && !funcs_to_infer_.is_empty()) {
+      funcs_to_infer_.RemoveLast();
+    }
+  }
+
+  // Infers a function name and leaves names collection state.
+  void Infer() {
+    DCHECK(IsOpen());
+    if (!funcs_to_infer_.is_empty()) {
+      InferFunctionsNames();
+    }
+  }
+
+ private:
+  enum NameType {
+    kEnclosingConstructorName,
+    kLiteralName,
+    kVariableName
+  };
+  struct Name {
+    Name(const AstRawString* name, NameType type) : name(name), type(type) {}
+    const AstRawString* name;
+    NameType type;
+  };
+
+  void Enter() { entries_stack_.Add(names_stack_.length(), zone()); }
+
+  void Leave() {
+    DCHECK(IsOpen());
+    names_stack_.Rewind(entries_stack_.RemoveLast());
+    if (entries_stack_.is_empty()) funcs_to_infer_.Clear();
+  }
+
+  Zone* zone() const { return zone_; }
+
+  // Constructs a full name in dotted notation from gathered names.
+  const AstString* MakeNameFromStack();
+
+  // A helper function for MakeNameFromStack.
+  const AstString* MakeNameFromStackHelper(int pos,
+                                               const AstString* prev);
+
+  // Performs name inferring for added functions.
+  void InferFunctionsNames();
+
+  AstValueFactory* ast_value_factory_;
+  ZoneList<int> entries_stack_;
+  ZoneList<Name> names_stack_;
+  ZoneList<FunctionLiteral*> funcs_to_infer_;
+  Zone* zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
+};
+
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_FUNC_NAME_INFERRER_H_
diff --git a/src/parsing/json-parser.h b/src/parsing/json-parser.h
new file mode 100644
index 0000000..e23c733
--- /dev/null
+++ b/src/parsing/json-parser.h
@@ -0,0 +1,842 @@
+// Copyright 2011 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_JSON_PARSER_H_
+#define V8_PARSING_JSON_PARSER_H_
+
+#include "src/char-predicates.h"
+#include "src/conversions.h"
+#include "src/debug/debug.h"
+#include "src/factory.h"
+#include "src/messages.h"
+#include "src/parsing/scanner.h"
+#include "src/parsing/token.h"
+#include "src/transitions.h"
+#include "src/types.h"
+
+namespace v8 {
+namespace internal {
+
+enum ParseElementResult { kElementFound, kElementNotFound, kNullHandle };
+
+
+// A simple json parser.
+template <bool seq_one_byte>
+class JsonParser BASE_EMBEDDED {
+ public:
+  MUST_USE_RESULT static MaybeHandle<Object> Parse(Handle<String> source) {
+    return JsonParser(source).ParseJson();
+  }
+
+  static const int kEndOfString = -1;
+
+ private:
+  explicit JsonParser(Handle<String> source)
+      : source_(source),
+        source_length_(source->length()),
+        isolate_(source->map()->GetHeap()->isolate()),
+        factory_(isolate_->factory()),
+        object_constructor_(isolate_->native_context()->object_function(),
+                            isolate_),
+        position_(-1) {
+    source_ = String::Flatten(source_);
+    pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
+
+    // Optimized fast case where we only have Latin1 characters.
+    if (seq_one_byte) {
+      seq_source_ = Handle<SeqOneByteString>::cast(source_);
+    }
+  }
+
+  // Parse a string containing a single JSON value.
+  MaybeHandle<Object> ParseJson();
+
+  inline void Advance() {
+    position_++;
+    if (position_ >= source_length_) {
+      c0_ = kEndOfString;
+    } else if (seq_one_byte) {
+      c0_ = seq_source_->SeqOneByteStringGet(position_);
+    } else {
+      c0_ = source_->Get(position_);
+    }
+  }
+
+  // The JSON lexical grammar is specified in the ECMAScript 5 standard,
+  // section 15.12.1.1. The only allowed whitespace characters between tokens
+  // are tab, carriage-return, newline and space.
+
+  inline void AdvanceSkipWhitespace() {
+    do {
+      Advance();
+    } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
+  }
+
+  inline void SkipWhitespace() {
+    while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
+      Advance();
+    }
+  }
+
+  inline uc32 AdvanceGetChar() {
+    Advance();
+    return c0_;
+  }
+
+  // Checks that current charater is c.
+  // If so, then consume c and skip whitespace.
+  inline bool MatchSkipWhiteSpace(uc32 c) {
+    if (c0_ == c) {
+      AdvanceSkipWhitespace();
+      return true;
+    }
+    return false;
+  }
+
+  // A JSON string (production JSONString) is subset of valid JavaScript string
+  // literals. The string must only be double-quoted (not single-quoted), and
+  // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
+  // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
+  Handle<String> ParseJsonString() {
+    return ScanJsonString<false>();
+  }
+
+  bool ParseJsonString(Handle<String> expected) {
+    int length = expected->length();
+    if (source_->length() - position_ - 1 > length) {
+      DisallowHeapAllocation no_gc;
+      String::FlatContent content = expected->GetFlatContent();
+      if (content.IsOneByte()) {
+        DCHECK_EQ('"', c0_);
+        const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
+        const uint8_t* expected_chars = content.ToOneByteVector().start();
+        for (int i = 0; i < length; i++) {
+          uint8_t c0 = input_chars[i];
+          if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
+            return false;
+          }
+        }
+        if (input_chars[length] == '"') {
+          position_ = position_ + length + 1;
+          AdvanceSkipWhitespace();
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  Handle<String> ParseJsonInternalizedString() {
+    return ScanJsonString<true>();
+  }
+
+  template <bool is_internalized>
+  Handle<String> ScanJsonString();
+  // Creates a new string and copies prefix[start..end] into the beginning
+  // of it. Then scans the rest of the string, adding characters after the
+  // prefix. Called by ScanJsonString when reaching a '\' or non-Latin1 char.
+  template <typename StringType, typename SinkChar>
+  Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
+
+  // A JSON number (production JSONNumber) is a subset of the valid JavaScript
+  // decimal number literals.
+  // It includes an optional minus sign, must have at least one
+  // digit before and after a decimal point, may not have prefixed zeros (unless
+  // the integer part is zero), and may include an exponent part (e.g., "e-10").
+  // Hexadecimal and octal numbers are not allowed.
+  Handle<Object> ParseJsonNumber();
+
+  // Parse a single JSON value from input (grammar production JSONValue).
+  // A JSON value is either a (double-quoted) string literal, a number literal,
+  // one of "true", "false", or "null", or an object or array literal.
+  Handle<Object> ParseJsonValue();
+
+  // Parse a JSON object literal (grammar production JSONObject).
+  // An object literal is a squiggly-braced and comma separated sequence
+  // (possibly empty) of key/value pairs, where the key is a JSON string
+  // literal, the value is a JSON value, and the two are separated by a colon.
+  // A JSON array doesn't allow numbers and identifiers as keys, like a
+  // JavaScript array.
+  Handle<Object> ParseJsonObject();
+
+  // Helper for ParseJsonObject. Parses the form "123": obj, which is recorded
+  // as an element, not a property.
+  ParseElementResult ParseElement(Handle<JSObject> json_object);
+
+  // Parses a JSON array literal (grammar production JSONArray). An array
+  // literal is a square-bracketed and comma separated sequence (possibly empty)
+  // of JSON values.
+  // A JSON array doesn't allow leaving out values from the sequence, nor does
+  // it allow a terminal comma, like a JavaScript array does.
+  Handle<Object> ParseJsonArray();
+
+
+  // Mark that a parsing error has happened at the current token, and
+  // return a null handle. Primarily for readability.
+  inline Handle<Object> ReportUnexpectedCharacter() {
+    return Handle<Object>::null();
+  }
+
+  inline Isolate* isolate() { return isolate_; }
+  inline Factory* factory() { return factory_; }
+  inline Handle<JSFunction> object_constructor() { return object_constructor_; }
+
+  static const int kInitialSpecialStringLength = 32;
+  static const int kPretenureTreshold = 100 * 1024;
+
+
+ private:
+  Zone* zone() { return &zone_; }
+
+  void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map,
+                               ZoneList<Handle<Object> >* properties);
+
+  Handle<String> source_;
+  int source_length_;
+  Handle<SeqOneByteString> seq_source_;
+
+  PretenureFlag pretenure_;
+  Isolate* isolate_;
+  Factory* factory_;
+  Zone zone_;
+  Handle<JSFunction> object_constructor_;
+  uc32 c0_;
+  int position_;
+};
+
+template <bool seq_one_byte>
+MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
+  // Advance to the first character (possibly EOS)
+  AdvanceSkipWhitespace();
+  Handle<Object> result = ParseJsonValue();
+  if (result.is_null() || c0_ != kEndOfString) {
+    // Some exception (for example stack overflow) is already pending.
+    if (isolate_->has_pending_exception()) return Handle<Object>::null();
+
+    // Parse failed. Current character is the unexpected token.
+    Factory* factory = this->factory();
+    MessageTemplate::Template message;
+    Handle<String> argument;
+
+    switch (c0_) {
+      case kEndOfString:
+        message = MessageTemplate::kUnexpectedEOS;
+        break;
+      case '-':
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        message = MessageTemplate::kUnexpectedTokenNumber;
+        break;
+      case '"':
+        message = MessageTemplate::kUnexpectedTokenString;
+        break;
+      default:
+        message = MessageTemplate::kUnexpectedToken;
+        argument = factory->LookupSingleCharacterStringFromCode(c0_);
+        break;
+    }
+
+    Handle<Script> script(factory->NewScript(source_));
+    // We should sent compile error event because we compile JSON object in
+    // separated source file.
+    isolate()->debug()->OnCompileError(script);
+    MessageLocation location(script, position_, position_ + 1);
+    Handle<Object> error = factory->NewSyntaxError(message, argument);
+    return isolate()->template Throw<Object>(error, &location);
+  }
+  return result;
+}
+
+
+// Parse any JSON value.
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
+  StackLimitCheck stack_check(isolate_);
+  if (stack_check.HasOverflowed()) {
+    isolate_->StackOverflow();
+    return Handle<Object>::null();
+  }
+
+  if (stack_check.InterruptRequested()) {
+    ExecutionAccess access(isolate_);
+    // Avoid blocking GC in long running parser (v8:3974).
+    isolate_->stack_guard()->HandleGCInterrupt();
+  }
+
+  if (c0_ == '"') return ParseJsonString();
+  if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
+  if (c0_ == '{') return ParseJsonObject();
+  if (c0_ == '[') return ParseJsonArray();
+  if (c0_ == 'f') {
+    if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
+        AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
+      AdvanceSkipWhitespace();
+      return factory()->false_value();
+    }
+    return ReportUnexpectedCharacter();
+  }
+  if (c0_ == 't') {
+    if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
+        AdvanceGetChar() == 'e') {
+      AdvanceSkipWhitespace();
+      return factory()->true_value();
+    }
+    return ReportUnexpectedCharacter();
+  }
+  if (c0_ == 'n') {
+    if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
+        AdvanceGetChar() == 'l') {
+      AdvanceSkipWhitespace();
+      return factory()->null_value();
+    }
+    return ReportUnexpectedCharacter();
+  }
+  return ReportUnexpectedCharacter();
+}
+
+
+template <bool seq_one_byte>
+ParseElementResult JsonParser<seq_one_byte>::ParseElement(
+    Handle<JSObject> json_object) {
+  uint32_t index = 0;
+  // Maybe an array index, try to parse it.
+  if (c0_ == '0') {
+    // With a leading zero, the string has to be "0" only to be an index.
+    Advance();
+  } else {
+    do {
+      int d = c0_ - '0';
+      if (index > 429496729U - ((d + 3) >> 3)) break;
+      index = (index * 10) + d;
+      Advance();
+    } while (IsDecimalDigit(c0_));
+  }
+
+  if (c0_ == '"') {
+    // Successfully parsed index, parse and store element.
+    AdvanceSkipWhitespace();
+
+    if (c0_ == ':') {
+      AdvanceSkipWhitespace();
+      Handle<Object> value = ParseJsonValue();
+      if (!value.is_null()) {
+        JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
+            .Assert();
+        return kElementFound;
+      } else {
+        return kNullHandle;
+      }
+    }
+  }
+  return kElementNotFound;
+}
+
+// Parse a JSON object. Position must be right at '{'.
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
+  HandleScope scope(isolate());
+  Handle<JSObject> json_object =
+      factory()->NewJSObject(object_constructor(), pretenure_);
+  Handle<Map> map(json_object->map());
+  int descriptor = 0;
+  ZoneList<Handle<Object> > properties(8, zone());
+  DCHECK_EQ(c0_, '{');
+
+  bool transitioning = true;
+
+  AdvanceSkipWhitespace();
+  if (c0_ != '}') {
+    do {
+      if (c0_ != '"') return ReportUnexpectedCharacter();
+
+      int start_position = position_;
+      Advance();
+
+      if (IsDecimalDigit(c0_)) {
+        ParseElementResult element_result = ParseElement(json_object);
+        if (element_result == kNullHandle) return Handle<Object>::null();
+        if (element_result == kElementFound) continue;
+      }
+      // Not an index, fallback to the slow path.
+
+      position_ = start_position;
+#ifdef DEBUG
+      c0_ = '"';
+#endif
+
+      Handle<String> key;
+      Handle<Object> value;
+
+      // Try to follow existing transitions as long as possible. Once we stop
+      // transitioning, no transition can be found anymore.
+      DCHECK(transitioning);
+      // First check whether there is a single expected transition. If so, try
+      // to parse it first.
+      bool follow_expected = false;
+      Handle<Map> target;
+      if (seq_one_byte) {
+        key = TransitionArray::ExpectedTransitionKey(map);
+        follow_expected = !key.is_null() && ParseJsonString(key);
+      }
+      // If the expected transition hits, follow it.
+      if (follow_expected) {
+        target = TransitionArray::ExpectedTransitionTarget(map);
+      } else {
+        // If the expected transition failed, parse an internalized string and
+        // try to find a matching transition.
+        key = ParseJsonInternalizedString();
+        if (key.is_null()) return ReportUnexpectedCharacter();
+
+        target = TransitionArray::FindTransitionToField(map, key);
+        // If a transition was found, follow it and continue.
+        transitioning = !target.is_null();
+      }
+      if (c0_ != ':') return ReportUnexpectedCharacter();
+
+      AdvanceSkipWhitespace();
+      value = ParseJsonValue();
+      if (value.is_null()) return ReportUnexpectedCharacter();
+
+      if (transitioning) {
+        PropertyDetails details =
+            target->instance_descriptors()->GetDetails(descriptor);
+        Representation expected_representation = details.representation();
+
+        if (value->FitsRepresentation(expected_representation)) {
+          if (expected_representation.IsHeapObject() &&
+              !target->instance_descriptors()
+                   ->GetFieldType(descriptor)
+                   ->NowContains(value)) {
+            Handle<HeapType> value_type(
+                value->OptimalType(isolate(), expected_representation));
+            Map::GeneralizeFieldType(target, descriptor,
+                                     expected_representation, value_type);
+          }
+          DCHECK(target->instance_descriptors()
+                     ->GetFieldType(descriptor)
+                     ->NowContains(value));
+          properties.Add(value, zone());
+          map = target;
+          descriptor++;
+          continue;
+        } else {
+          transitioning = false;
+        }
+      }
+
+      DCHECK(!transitioning);
+
+      // Commit the intermediate state to the object and stop transitioning.
+      CommitStateToJsonObject(json_object, map, &properties);
+
+      JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
+          .Check();
+    } while (transitioning && MatchSkipWhiteSpace(','));
+
+    // If we transitioned until the very end, transition the map now.
+    if (transitioning) {
+      CommitStateToJsonObject(json_object, map, &properties);
+    } else {
+      while (MatchSkipWhiteSpace(',')) {
+        HandleScope local_scope(isolate());
+        if (c0_ != '"') return ReportUnexpectedCharacter();
+
+        int start_position = position_;
+        Advance();
+
+        if (IsDecimalDigit(c0_)) {
+          ParseElementResult element_result = ParseElement(json_object);
+          if (element_result == kNullHandle) return Handle<Object>::null();
+          if (element_result == kElementFound) continue;
+        }
+        // Not an index, fallback to the slow path.
+
+        position_ = start_position;
+#ifdef DEBUG
+        c0_ = '"';
+#endif
+
+        Handle<String> key;
+        Handle<Object> value;
+
+        key = ParseJsonInternalizedString();
+        if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
+
+        AdvanceSkipWhitespace();
+        value = ParseJsonValue();
+        if (value.is_null()) return ReportUnexpectedCharacter();
+
+        JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
+                                                          value).Check();
+      }
+    }
+
+    if (c0_ != '}') {
+      return ReportUnexpectedCharacter();
+    }
+  }
+  AdvanceSkipWhitespace();
+  return scope.CloseAndEscape(json_object);
+}
+
+
+template <bool seq_one_byte>
+void JsonParser<seq_one_byte>::CommitStateToJsonObject(
+    Handle<JSObject> json_object, Handle<Map> map,
+    ZoneList<Handle<Object> >* properties) {
+  JSObject::AllocateStorageForMap(json_object, map);
+  DCHECK(!json_object->map()->is_dictionary_map());
+
+  DisallowHeapAllocation no_gc;
+
+  int length = properties->length();
+  for (int i = 0; i < length; i++) {
+    Handle<Object> value = (*properties)[i];
+    json_object->WriteToField(i, *value);
+  }
+}
+
+
+// Parse a JSON array. Position must be right at '['.
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
+  HandleScope scope(isolate());
+  ZoneList<Handle<Object> > elements(4, zone());
+  DCHECK_EQ(c0_, '[');
+
+  AdvanceSkipWhitespace();
+  if (c0_ != ']') {
+    do {
+      Handle<Object> element = ParseJsonValue();
+      if (element.is_null()) return ReportUnexpectedCharacter();
+      elements.Add(element, zone());
+    } while (MatchSkipWhiteSpace(','));
+    if (c0_ != ']') {
+      return ReportUnexpectedCharacter();
+    }
+  }
+  AdvanceSkipWhitespace();
+  // Allocate a fixed array with all the elements.
+  Handle<FixedArray> fast_elements =
+      factory()->NewFixedArray(elements.length(), pretenure_);
+  for (int i = 0, n = elements.length(); i < n; i++) {
+    fast_elements->set(i, *elements[i]);
+  }
+  Handle<Object> json_array = factory()->NewJSArrayWithElements(
+      fast_elements, FAST_ELEMENTS, Strength::WEAK, pretenure_);
+  return scope.CloseAndEscape(json_array);
+}
+
+
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
+  bool negative = false;
+  int beg_pos = position_;
+  if (c0_ == '-') {
+    Advance();
+    negative = true;
+  }
+  if (c0_ == '0') {
+    Advance();
+    // Prefix zero is only allowed if it's the only digit before
+    // a decimal point or exponent.
+    if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
+  } else {
+    int i = 0;
+    int digits = 0;
+    if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
+    do {
+      i = i * 10 + c0_ - '0';
+      digits++;
+      Advance();
+    } while (IsDecimalDigit(c0_));
+    if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
+      SkipWhitespace();
+      return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
+    }
+  }
+  if (c0_ == '.') {
+    Advance();
+    if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
+    do {
+      Advance();
+    } while (IsDecimalDigit(c0_));
+  }
+  if (AsciiAlphaToLower(c0_) == 'e') {
+    Advance();
+    if (c0_ == '-' || c0_ == '+') Advance();
+    if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
+    do {
+      Advance();
+    } while (IsDecimalDigit(c0_));
+  }
+  int length = position_ - beg_pos;
+  double number;
+  if (seq_one_byte) {
+    Vector<const uint8_t> chars(seq_source_->GetChars() +  beg_pos, length);
+    number = StringToDouble(isolate()->unicode_cache(), chars,
+                            NO_FLAGS,  // Hex, octal or trailing junk.
+                            std::numeric_limits<double>::quiet_NaN());
+  } else {
+    Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
+    String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
+    Vector<const uint8_t> result =
+        Vector<const uint8_t>(buffer.start(), length);
+    number = StringToDouble(isolate()->unicode_cache(),
+                            result,
+                            NO_FLAGS,  // Hex, octal or trailing junk.
+                            0.0);
+    buffer.Dispose();
+  }
+  SkipWhitespace();
+  return factory()->NewNumber(number, pretenure_);
+}
+
+
+template <typename StringType>
+inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
+
+template <>
+inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
+  seq_str->SeqTwoByteStringSet(i, c);
+}
+
+template <>
+inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
+  seq_str->SeqOneByteStringSet(i, c);
+}
+
+template <typename StringType>
+inline Handle<StringType> NewRawString(Factory* factory,
+                                       int length,
+                                       PretenureFlag pretenure);
+
+template <>
+inline Handle<SeqTwoByteString> NewRawString(Factory* factory,
+                                             int length,
+                                             PretenureFlag pretenure) {
+  return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
+}
+
+template <>
+inline Handle<SeqOneByteString> NewRawString(Factory* factory,
+                                           int length,
+                                           PretenureFlag pretenure) {
+  return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
+}
+
+
+// Scans the rest of a JSON string starting from position_ and writes
+// prefix[start..end] along with the scanned characters into a
+// sequential string of type StringType.
+template <bool seq_one_byte>
+template <typename StringType, typename SinkChar>
+Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
+    Handle<String> prefix, int start, int end) {
+  int count = end - start;
+  int max_length = count + source_length_ - position_;
+  int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
+  Handle<StringType> seq_string =
+      NewRawString<StringType>(factory(), length, pretenure_);
+  // Copy prefix into seq_str.
+  SinkChar* dest = seq_string->GetChars();
+  String::WriteToFlat(*prefix, dest, start, end);
+
+  while (c0_ != '"') {
+    // Check for control character (0x00-0x1f) or unterminated string (<0).
+    if (c0_ < 0x20) return Handle<String>::null();
+    if (count >= length) {
+      // We need to create a longer sequential string for the result.
+      return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
+    }
+    if (c0_ != '\\') {
+      // If the sink can contain UC16 characters, or source_ contains only
+      // Latin1 characters, there's no need to test whether we can store the
+      // character. Otherwise check whether the UC16 source character can fit
+      // in the Latin1 sink.
+      if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
+          c0_ <= String::kMaxOneByteCharCode) {
+        SeqStringSet(seq_string, count++, c0_);
+        Advance();
+      } else {
+        // StringType is SeqOneByteString and we just read a non-Latin1 char.
+        return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
+      }
+    } else {
+      Advance();  // Advance past the \.
+      switch (c0_) {
+        case '"':
+        case '\\':
+        case '/':
+          SeqStringSet(seq_string, count++, c0_);
+          break;
+        case 'b':
+          SeqStringSet(seq_string, count++, '\x08');
+          break;
+        case 'f':
+          SeqStringSet(seq_string, count++, '\x0c');
+          break;
+        case 'n':
+          SeqStringSet(seq_string, count++, '\x0a');
+          break;
+        case 'r':
+          SeqStringSet(seq_string, count++, '\x0d');
+          break;
+        case 't':
+          SeqStringSet(seq_string, count++, '\x09');
+          break;
+        case 'u': {
+          uc32 value = 0;
+          for (int i = 0; i < 4; i++) {
+            Advance();
+            int digit = HexValue(c0_);
+            if (digit < 0) {
+              return Handle<String>::null();
+            }
+            value = value * 16 + digit;
+          }
+          if (sizeof(SinkChar) == kUC16Size ||
+              value <= String::kMaxOneByteCharCode) {
+            SeqStringSet(seq_string, count++, value);
+            break;
+          } else {
+            // StringType is SeqOneByteString and we just read a non-Latin1
+            // char.
+            position_ -= 6;  // Rewind position_ to \ in \uxxxx.
+            Advance();
+            return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
+                                                              0,
+                                                              count);
+          }
+        }
+        default:
+          return Handle<String>::null();
+      }
+      Advance();
+    }
+  }
+
+  DCHECK_EQ('"', c0_);
+  // Advance past the last '"'.
+  AdvanceSkipWhitespace();
+
+  // Shrink seq_string length to count and return.
+  return SeqString::Truncate(seq_string, count);
+}
+
+
+template <bool seq_one_byte>
+template <bool is_internalized>
+Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
+  DCHECK_EQ('"', c0_);
+  Advance();
+  if (c0_ == '"') {
+    AdvanceSkipWhitespace();
+    return factory()->empty_string();
+  }
+
+  if (seq_one_byte && is_internalized) {
+    // Fast path for existing internalized strings.  If the the string being
+    // parsed is not a known internalized string, contains backslashes or
+    // unexpectedly reaches the end of string, return with an empty handle.
+    uint32_t running_hash = isolate()->heap()->HashSeed();
+    int position = position_;
+    uc32 c0 = c0_;
+    do {
+      if (c0 == '\\') {
+        c0_ = c0;
+        int beg_pos = position_;
+        position_ = position;
+        return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
+                                                             beg_pos,
+                                                             position_);
+      }
+      if (c0 < 0x20) return Handle<String>::null();
+      running_hash = StringHasher::AddCharacterCore(running_hash,
+                                                    static_cast<uint16_t>(c0));
+      position++;
+      if (position >= source_length_) return Handle<String>::null();
+      c0 = seq_source_->SeqOneByteStringGet(position);
+    } while (c0 != '"');
+    int length = position - position_;
+    uint32_t hash = (length <= String::kMaxHashCalcLength)
+                        ? StringHasher::GetHashCore(running_hash)
+                        : static_cast<uint32_t>(length);
+    Vector<const uint8_t> string_vector(
+        seq_source_->GetChars() + position_, length);
+    StringTable* string_table = isolate()->heap()->string_table();
+    uint32_t capacity = string_table->Capacity();
+    uint32_t entry = StringTable::FirstProbe(hash, capacity);
+    uint32_t count = 1;
+    Handle<String> result;
+    while (true) {
+      Object* element = string_table->KeyAt(entry);
+      if (element == isolate()->heap()->undefined_value()) {
+        // Lookup failure.
+        result = factory()->InternalizeOneByteString(
+            seq_source_, position_, length);
+        break;
+      }
+      if (element != isolate()->heap()->the_hole_value() &&
+          String::cast(element)->IsOneByteEqualTo(string_vector)) {
+        result = Handle<String>(String::cast(element), isolate());
+#ifdef DEBUG
+        uint32_t hash_field =
+            (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
+        DCHECK_EQ(static_cast<int>(result->Hash()),
+                  static_cast<int>(hash_field >> String::kHashShift));
+#endif
+        break;
+      }
+      entry = StringTable::NextProbe(entry, count++, capacity);
+    }
+    position_ = position;
+    // Advance past the last '"'.
+    AdvanceSkipWhitespace();
+    return result;
+  }
+
+  int beg_pos = position_;
+  // Fast case for Latin1 only without escape characters.
+  do {
+    // Check for control character (0x00-0x1f) or unterminated string (<0).
+    if (c0_ < 0x20) return Handle<String>::null();
+    if (c0_ != '\\') {
+      if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
+        Advance();
+      } else {
+        return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
+                                                          beg_pos,
+                                                          position_);
+      }
+    } else {
+      return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
+                                                           beg_pos,
+                                                           position_);
+    }
+  } while (c0_ != '"');
+  int length = position_ - beg_pos;
+  Handle<String> result =
+      factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
+  uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
+  String::WriteToFlat(*source_, dest, beg_pos, position_);
+
+  DCHECK_EQ('"', c0_);
+  // Advance past the last '"'.
+  AdvanceSkipWhitespace();
+  return result;
+}
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_JSON_PARSER_H_
diff --git a/src/parsing/parameter-initializer-rewriter.cc b/src/parsing/parameter-initializer-rewriter.cc
new file mode 100644
index 0000000..003bbeb
--- /dev/null
+++ b/src/parsing/parameter-initializer-rewriter.cc
@@ -0,0 +1,88 @@
+// Copyright 2015 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.
+
+#include "src/parsing/parameter-initializer-rewriter.h"
+
+#include "src/ast/ast.h"
+#include "src/ast/ast-expression-visitor.h"
+#include "src/ast/scopes.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+
+class Rewriter final : public AstExpressionVisitor {
+ public:
+  Rewriter(uintptr_t stack_limit, Expression* initializer, Scope* old_scope,
+           Scope* new_scope)
+      : AstExpressionVisitor(stack_limit, initializer),
+        old_scope_(old_scope),
+        new_scope_(new_scope) {}
+
+ private:
+  void VisitExpression(Expression* expr) override {}
+
+  void VisitFunctionLiteral(FunctionLiteral* expr) override;
+  void VisitClassLiteral(ClassLiteral* expr) override;
+  void VisitVariableProxy(VariableProxy* expr) override;
+
+  Scope* old_scope_;
+  Scope* new_scope_;
+};
+
+
+void Rewriter::VisitFunctionLiteral(FunctionLiteral* function_literal) {
+  function_literal->scope()->ReplaceOuterScope(new_scope_);
+}
+
+
+void Rewriter::VisitClassLiteral(ClassLiteral* class_literal) {
+  class_literal->scope()->ReplaceOuterScope(new_scope_);
+  if (class_literal->extends() != nullptr) {
+    Visit(class_literal->extends());
+  }
+  // No need to visit the constructor since it will have the class
+  // scope on its scope chain.
+  ZoneList<ObjectLiteralProperty*>* props = class_literal->properties();
+  for (int i = 0; i < props->length(); ++i) {
+    ObjectLiteralProperty* prop = props->at(i);
+    if (!prop->key()->IsLiteral()) {
+      Visit(prop->key());
+    }
+    // No need to visit the values, since all values are functions with
+    // the class scope on their scope chain.
+    DCHECK(prop->value()->IsFunctionLiteral());
+  }
+}
+
+
+void Rewriter::VisitVariableProxy(VariableProxy* proxy) {
+  if (proxy->is_resolved()) {
+    Variable* var = proxy->var();
+    DCHECK_EQ(var->mode(), TEMPORARY);
+    if (old_scope_->RemoveTemporary(var)) {
+      var->set_scope(new_scope_);
+      new_scope_->AddTemporary(var);
+    }
+  } else if (old_scope_->RemoveUnresolved(proxy)) {
+    new_scope_->AddUnresolved(proxy);
+  }
+}
+
+
+}  // anonymous namespace
+
+
+void RewriteParameterInitializerScope(uintptr_t stack_limit,
+                                      Expression* initializer, Scope* old_scope,
+                                      Scope* new_scope) {
+  Rewriter rewriter(stack_limit, initializer, old_scope, new_scope);
+  rewriter.Run();
+}
+
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/parameter-initializer-rewriter.h b/src/parsing/parameter-initializer-rewriter.h
new file mode 100644
index 0000000..255534c
--- /dev/null
+++ b/src/parsing/parameter-initializer-rewriter.h
@@ -0,0 +1,22 @@
+// Copyright 2015 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_PARAMETER_EXPRESSION_REWRITER_H_
+#define V8_PARSING_PARAMETER_EXPRESSION_REWRITER_H_
+
+#include "src/ast/ast.h"
+
+namespace v8 {
+namespace internal {
+
+
+void RewriteParameterInitializerScope(uintptr_t stack_limit,
+                                      Expression* initializer, Scope* old_scope,
+                                      Scope* new_scope);
+
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_PARAMETER_EXPRESSION_REWRITER_H_
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
new file mode 100644
index 0000000..d9da445
--- /dev/null
+++ b/src/parsing/parser-base.h
@@ -0,0 +1,3381 @@
+// 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_BASE_H
+#define V8_PARSING_PARSER_BASE_H
+
+#include "src/ast/scopes.h"
+#include "src/bailout-reason.h"
+#include "src/hashmap.h"
+#include "src/messages.h"
+#include "src/parsing/expression-classifier.h"
+#include "src/parsing/func-name-inferrer.h"
+#include "src/parsing/scanner.h"
+#include "src/parsing/token.h"
+
+namespace v8 {
+namespace internal {
+
+
+enum FunctionNameValidity {
+  kFunctionNameIsStrictReserved,
+  kSkipFunctionNameCheck,
+  kFunctionNameValidityUnknown
+};
+
+
+struct FormalParametersBase {
+  explicit FormalParametersBase(Scope* scope) : scope(scope) {}
+  Scope* scope;
+  bool has_rest = false;
+  bool is_simple = true;
+  int materialized_literals_count = 0;
+};
+
+
+// Common base class shared between parser and pre-parser. Traits encapsulate
+// the differences between Parser and PreParser:
+
+// - Return types: For example, Parser functions return Expression* and
+// PreParser functions return PreParserExpression.
+
+// - Creating parse tree nodes: Parser generates an AST during the recursive
+// descent. 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.
+
+// - Miscellaneous other tasks interleaved with the recursive descent. For
+// example, Parser keeps track of which function literals should be marked as
+// pretenured, and PreParser doesn't care.
+
+// The traits are expected to contain the following typedefs:
+// struct Traits {
+//   // In particular...
+//   struct Type {
+//     // Used by FunctionState and BlockState.
+//     typedef Scope;
+//     typedef GeneratorVariable;
+//     // Return types for traversing functions.
+//     typedef Identifier;
+//     typedef Expression;
+//     typedef FunctionLiteral;
+//     typedef ClassLiteral;
+//     typedef ObjectLiteralProperty;
+//     typedef Literal;
+//     typedef ExpressionList;
+//     typedef PropertyList;
+//     typedef FormalParameter;
+//     typedef FormalParameters;
+//     // For constructing objects returned by the traversing functions.
+//     typedef Factory;
+//   };
+//   // ...
+// };
+
+template <typename Traits>
+class ParserBase : public Traits {
+ public:
+  // Shorten type names defined by Traits.
+  typedef typename Traits::Type::Expression ExpressionT;
+  typedef typename Traits::Type::Identifier IdentifierT;
+  typedef typename Traits::Type::FormalParameter FormalParameterT;
+  typedef typename Traits::Type::FormalParameters FormalParametersT;
+  typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
+  typedef typename Traits::Type::Literal LiteralT;
+  typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
+  typedef typename Traits::Type::StatementList StatementListT;
+
+  ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
+             v8::Extension* extension, AstValueFactory* ast_value_factory,
+             ParserRecorder* log, typename Traits::Type::Parser this_object)
+      : Traits(this_object),
+        parenthesized_function_(false),
+        scope_(NULL),
+        function_state_(NULL),
+        extension_(extension),
+        fni_(NULL),
+        ast_value_factory_(ast_value_factory),
+        log_(log),
+        mode_(PARSE_EAGERLY),  // Lazy mode must be set explicitly.
+        stack_limit_(stack_limit),
+        zone_(zone),
+        scanner_(scanner),
+        stack_overflow_(false),
+        allow_lazy_(false),
+        allow_natives_(false),
+        allow_harmony_sloppy_(false),
+        allow_harmony_sloppy_function_(false),
+        allow_harmony_sloppy_let_(false),
+        allow_harmony_default_parameters_(false),
+        allow_harmony_destructuring_bind_(false),
+        allow_harmony_destructuring_assignment_(false),
+        allow_strong_mode_(false),
+        allow_legacy_const_(true),
+        allow_harmony_do_expressions_(false),
+        allow_harmony_function_name_(false) {}
+
+#define ALLOW_ACCESSORS(name)                           \
+  bool allow_##name() const { return allow_##name##_; } \
+  void set_allow_##name(bool allow) { allow_##name##_ = allow; }
+
+  ALLOW_ACCESSORS(lazy);
+  ALLOW_ACCESSORS(natives);
+  ALLOW_ACCESSORS(harmony_sloppy);
+  ALLOW_ACCESSORS(harmony_sloppy_function);
+  ALLOW_ACCESSORS(harmony_sloppy_let);
+  ALLOW_ACCESSORS(harmony_default_parameters);
+  ALLOW_ACCESSORS(harmony_destructuring_bind);
+  ALLOW_ACCESSORS(harmony_destructuring_assignment);
+  ALLOW_ACCESSORS(strong_mode);
+  ALLOW_ACCESSORS(legacy_const);
+  ALLOW_ACCESSORS(harmony_do_expressions);
+  ALLOW_ACCESSORS(harmony_function_name);
+#undef ALLOW_ACCESSORS
+
+  uintptr_t stack_limit() const { return stack_limit_; }
+
+ protected:
+  enum AllowRestrictedIdentifiers {
+    kAllowRestrictedIdentifiers,
+    kDontAllowRestrictedIdentifiers
+  };
+
+  enum Mode {
+    PARSE_LAZILY,
+    PARSE_EAGERLY
+  };
+
+  enum VariableDeclarationContext {
+    kStatementListItem,
+    kStatement,
+    kForStatement
+  };
+
+  class Checkpoint;
+  class ObjectLiteralCheckerBase;
+
+  // ---------------------------------------------------------------------------
+  // FunctionState and BlockState together implement the parser's scope stack.
+  // The parser's current scope is in scope_. BlockState and FunctionState
+  // constructors push on the scope stack and the destructors pop. They are also
+  // used to hold the parser's per-function and per-block state.
+  class BlockState BASE_EMBEDDED {
+   public:
+    BlockState(Scope** scope_stack, Scope* scope)
+        : scope_stack_(scope_stack), outer_scope_(*scope_stack) {
+      *scope_stack_ = scope;
+    }
+    ~BlockState() { *scope_stack_ = outer_scope_; }
+
+   private:
+    Scope** scope_stack_;
+    Scope* outer_scope_;
+  };
+
+  struct DestructuringAssignment {
+   public:
+    DestructuringAssignment(ExpressionT expression, Scope* scope)
+        : assignment(expression), scope(scope) {}
+
+    ExpressionT assignment;
+    Scope* scope;
+  };
+
+  class FunctionState BASE_EMBEDDED {
+   public:
+    FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
+                  Scope* scope, FunctionKind kind,
+                  typename Traits::Type::Factory* factory);
+    ~FunctionState();
+
+    int NextMaterializedLiteralIndex() {
+      return next_materialized_literal_index_++;
+    }
+    int materialized_literal_count() {
+      return next_materialized_literal_index_;
+    }
+
+    void SkipMaterializedLiterals(int count) {
+      next_materialized_literal_index_ += count;
+    }
+
+    void AddProperty() { expected_property_count_++; }
+    int expected_property_count() { return expected_property_count_; }
+
+    Scanner::Location this_location() const { return this_location_; }
+    Scanner::Location super_location() const { return super_location_; }
+    Scanner::Location return_location() const { return return_location_; }
+    void set_this_location(Scanner::Location location) {
+      this_location_ = location;
+    }
+    void set_super_location(Scanner::Location location) {
+      super_location_ = location;
+    }
+    void set_return_location(Scanner::Location location) {
+      return_location_ = location;
+    }
+
+    bool is_generator() const { return IsGeneratorFunction(kind_); }
+
+    FunctionKind kind() const { return kind_; }
+    FunctionState* outer() const { return outer_function_state_; }
+
+    void set_generator_object_variable(
+        typename Traits::Type::GeneratorVariable* variable) {
+      DCHECK(variable != NULL);
+      DCHECK(is_generator());
+      generator_object_variable_ = variable;
+    }
+    typename Traits::Type::GeneratorVariable* generator_object_variable()
+        const {
+      return generator_object_variable_;
+    }
+
+    typename Traits::Type::Factory* factory() { return factory_; }
+
+    const List<DestructuringAssignment>& destructuring_assignments_to_rewrite()
+        const {
+      return destructuring_assignments_to_rewrite_;
+    }
+
+    void AddDestructuringAssignment(DestructuringAssignment pair) {
+      destructuring_assignments_to_rewrite_.Add(pair);
+    }
+
+   private:
+    // Used to assign an index to each literal that needs materialization in
+    // the function.  Includes regexp literals, and boilerplate for object and
+    // array literals.
+    int next_materialized_literal_index_;
+
+    // Properties count estimation.
+    int expected_property_count_;
+
+    // Location of most recent use of 'this' (invalid if none).
+    Scanner::Location this_location_;
+
+    // Location of most recent 'return' statement (invalid if none).
+    Scanner::Location return_location_;
+
+    // Location of call to the "super" constructor (invalid if none).
+    Scanner::Location super_location_;
+
+    FunctionKind kind_;
+    // For generators, this variable may hold the generator object. It variable
+    // is used by yield expressions and return statements. It is not necessary
+    // for generator functions to have this variable set.
+    Variable* generator_object_variable_;
+
+    FunctionState** function_state_stack_;
+    FunctionState* outer_function_state_;
+    Scope** scope_stack_;
+    Scope* outer_scope_;
+
+    List<DestructuringAssignment> destructuring_assignments_to_rewrite_;
+
+    void RewriteDestructuringAssignments();
+
+    typename Traits::Type::Factory* factory_;
+
+    friend class ParserTraits;
+    friend class Checkpoint;
+  };
+
+  // Annoyingly, arrow functions first parse as comma expressions, then when we
+  // see the => we have to go back and reinterpret the arguments as being formal
+  // parameters.  To do so we need to reset some of the parser state back to
+  // what it was before the arguments were first seen.
+  class Checkpoint BASE_EMBEDDED {
+   public:
+    explicit Checkpoint(ParserBase* parser) {
+      function_state_ = parser->function_state_;
+      next_materialized_literal_index_ =
+          function_state_->next_materialized_literal_index_;
+      expected_property_count_ = function_state_->expected_property_count_;
+    }
+
+    void Restore(int* materialized_literal_index_delta) {
+      *materialized_literal_index_delta =
+          function_state_->next_materialized_literal_index_ -
+          next_materialized_literal_index_;
+      function_state_->next_materialized_literal_index_ =
+          next_materialized_literal_index_;
+      function_state_->expected_property_count_ = expected_property_count_;
+    }
+
+   private:
+    FunctionState* function_state_;
+    int next_materialized_literal_index_;
+    int expected_property_count_;
+  };
+
+  class ParsingModeScope BASE_EMBEDDED {
+   public:
+    ParsingModeScope(ParserBase* parser, Mode mode)
+        : parser_(parser),
+          old_mode_(parser->mode()) {
+      parser_->mode_ = mode;
+    }
+    ~ParsingModeScope() {
+      parser_->mode_ = old_mode_;
+    }
+
+   private:
+    ParserBase* parser_;
+    Mode old_mode_;
+  };
+
+  Scope* NewScope(Scope* parent, ScopeType scope_type) {
+    // Must always pass the function kind for FUNCTION_SCOPE.
+    DCHECK(scope_type != FUNCTION_SCOPE);
+    return NewScope(parent, scope_type, kNormalFunction);
+  }
+
+  Scope* NewScope(Scope* parent, ScopeType scope_type, FunctionKind kind) {
+    DCHECK(ast_value_factory());
+    DCHECK(scope_type != MODULE_SCOPE || FLAG_harmony_modules);
+    Scope* result = new (zone())
+        Scope(zone(), parent, scope_type, ast_value_factory(), kind);
+    result->Initialize();
+    return result;
+  }
+
+  Scanner* scanner() const { return scanner_; }
+  AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
+  int position() { return scanner_->location().beg_pos; }
+  int peek_position() { return scanner_->peek_location().beg_pos; }
+  bool stack_overflow() const { return stack_overflow_; }
+  void set_stack_overflow() { stack_overflow_ = true; }
+  Mode mode() const { return mode_; }
+  Zone* zone() const { return zone_; }
+
+  INLINE(Token::Value peek()) {
+    if (stack_overflow_) return Token::ILLEGAL;
+    return scanner()->peek();
+  }
+
+  INLINE(Token::Value PeekAhead()) {
+    if (stack_overflow_) return Token::ILLEGAL;
+    return scanner()->PeekAhead();
+  }
+
+  INLINE(Token::Value Next()) {
+    if (stack_overflow_) return Token::ILLEGAL;
+    {
+      if (GetCurrentStackPosition() < stack_limit_) {
+        // Any further calls to Next or peek will return the illegal token.
+        // The current call must return the next token, which might already
+        // have been peek'ed.
+        stack_overflow_ = true;
+      }
+    }
+    return scanner()->Next();
+  }
+
+  void Consume(Token::Value token) {
+    Token::Value next = Next();
+    USE(next);
+    USE(token);
+    DCHECK(next == token);
+  }
+
+  bool Check(Token::Value token) {
+    Token::Value next = peek();
+    if (next == token) {
+      Consume(next);
+      return true;
+    }
+    return false;
+  }
+
+  void Expect(Token::Value token, bool* ok) {
+    Token::Value next = Next();
+    if (next != token) {
+      ReportUnexpectedToken(next);
+      *ok = false;
+    }
+  }
+
+  void ExpectSemicolon(bool* ok) {
+    // Check for automatic semicolon insertion according to
+    // the rules given in ECMA-262, section 7.9, page 21.
+    Token::Value tok = peek();
+    if (tok == Token::SEMICOLON) {
+      Next();
+      return;
+    }
+    if (scanner()->HasAnyLineTerminatorBeforeNext() ||
+        tok == Token::RBRACE ||
+        tok == Token::EOS) {
+      return;
+    }
+    Expect(Token::SEMICOLON, ok);
+  }
+
+  bool peek_any_identifier() {
+    Token::Value next = peek();
+    return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD ||
+           next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
+           next == Token::STATIC || next == Token::YIELD;
+  }
+
+  bool CheckContextualKeyword(Vector<const char> keyword) {
+    if (PeekContextualKeyword(keyword)) {
+      Consume(Token::IDENTIFIER);
+      return true;
+    }
+    return false;
+  }
+
+  bool PeekContextualKeyword(Vector<const char> keyword) {
+    return peek() == Token::IDENTIFIER &&
+           scanner()->is_next_contextual_keyword(keyword);
+  }
+
+  void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
+    Expect(Token::IDENTIFIER, ok);
+    if (!*ok) return;
+    if (!scanner()->is_literal_contextual_keyword(keyword)) {
+      ReportUnexpectedToken(scanner()->current_token());
+      *ok = false;
+    }
+  }
+
+  bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) {
+    if (Check(Token::IN)) {
+      if (is_strong(language_mode())) {
+        ReportMessageAt(scanner()->location(), MessageTemplate::kStrongForIn);
+        *ok = false;
+      } else {
+        *visit_mode = ForEachStatement::ENUMERATE;
+      }
+      return true;
+    } else if (CheckContextualKeyword(CStrVector("of"))) {
+      *visit_mode = ForEachStatement::ITERATE;
+      return true;
+    }
+    return false;
+  }
+
+  // Checks whether an octal literal was last seen between beg_pos and end_pos.
+  // If so, reports an error. Only called for strict mode and template strings.
+  void CheckOctalLiteral(int beg_pos, int end_pos,
+                         MessageTemplate::Template message, bool* ok) {
+    Scanner::Location octal = scanner()->octal_position();
+    if (octal.IsValid() && beg_pos <= octal.beg_pos &&
+        octal.end_pos <= end_pos) {
+      ReportMessageAt(octal, message);
+      scanner()->clear_octal_position();
+      *ok = false;
+    }
+  }
+
+  inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) {
+    CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral,
+                      ok);
+  }
+
+  inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) {
+    CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral,
+                      ok);
+  }
+
+  void CheckDestructuringElement(ExpressionT element,
+                                 ExpressionClassifier* classifier, int beg_pos,
+                                 int end_pos);
+
+  // Checking the name of a function literal. This has to be done after parsing
+  // the function, since the function can declare itself strict.
+  void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name,
+                         FunctionNameValidity function_name_validity,
+                         const Scanner::Location& function_name_loc, bool* ok) {
+    if (function_name_validity == kSkipFunctionNameCheck) return;
+    // The function name needs to be checked in strict mode.
+    if (is_sloppy(language_mode)) return;
+
+    if (this->IsEvalOrArguments(function_name)) {
+      Traits::ReportMessageAt(function_name_loc,
+                              MessageTemplate::kStrictEvalArguments);
+      *ok = false;
+      return;
+    }
+    if (function_name_validity == kFunctionNameIsStrictReserved) {
+      Traits::ReportMessageAt(function_name_loc,
+                              MessageTemplate::kUnexpectedStrictReserved);
+      *ok = false;
+      return;
+    }
+    if (is_strong(language_mode) && this->IsUndefined(function_name)) {
+      Traits::ReportMessageAt(function_name_loc,
+                              MessageTemplate::kStrongUndefined);
+      *ok = false;
+      return;
+    }
+  }
+
+  // Determine precedence of given token.
+  static int Precedence(Token::Value token, bool accept_IN) {
+    if (token == Token::IN && !accept_IN)
+      return 0;  // 0 precedence will terminate binary expression parsing
+    return Token::Precedence(token);
+  }
+
+  typename Traits::Type::Factory* factory() {
+    return function_state_->factory();
+  }
+
+  LanguageMode language_mode() { return scope_->language_mode(); }
+  bool is_generator() const { return function_state_->is_generator(); }
+
+  bool allow_const() {
+    return is_strict(language_mode()) || allow_harmony_sloppy() ||
+           allow_legacy_const();
+  }
+
+  bool allow_let() {
+    return is_strict(language_mode()) || allow_harmony_sloppy_let();
+  }
+
+  // Report syntax errors.
+  void ReportMessage(MessageTemplate::Template message, const char* arg = NULL,
+                     ParseErrorType error_type = kSyntaxError) {
+    Scanner::Location source_location = scanner()->location();
+    Traits::ReportMessageAt(source_location, message, arg, error_type);
+  }
+
+  void ReportMessageAt(Scanner::Location location,
+                       MessageTemplate::Template message,
+                       ParseErrorType error_type = kSyntaxError) {
+    Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0),
+                            error_type);
+  }
+
+  void GetUnexpectedTokenMessage(
+      Token::Value token, MessageTemplate::Template* message, const char** arg,
+      MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken);
+
+  void ReportUnexpectedToken(Token::Value token);
+  void ReportUnexpectedTokenAt(
+      Scanner::Location location, Token::Value token,
+      MessageTemplate::Template message = MessageTemplate::kUnexpectedToken);
+
+
+  void ReportClassifierError(const ExpressionClassifier::Error& error) {
+    Traits::ReportMessageAt(error.location, error.message, error.arg,
+                            error.type);
+  }
+
+  void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) {
+    if (!classifier->is_valid_expression() ||
+        classifier->has_cover_initialized_name()) {
+      const Scanner::Location& a = classifier->expression_error().location;
+      const Scanner::Location& b =
+          classifier->cover_initialized_name_error().location;
+      if (a.beg_pos < 0 || (b.beg_pos >= 0 && a.beg_pos > b.beg_pos)) {
+        ReportClassifierError(classifier->cover_initialized_name_error());
+      } else {
+        ReportClassifierError(classifier->expression_error());
+      }
+      *ok = false;
+    }
+  }
+
+  void ValidateFormalParameterInitializer(
+      const ExpressionClassifier* classifier, bool* ok) {
+    if (!classifier->is_valid_formal_parameter_initializer()) {
+      ReportClassifierError(classifier->formal_parameter_initializer_error());
+      *ok = false;
+    }
+  }
+
+  void ValidateBindingPattern(const ExpressionClassifier* classifier,
+                              bool* ok) {
+    if (!classifier->is_valid_binding_pattern()) {
+      ReportClassifierError(classifier->binding_pattern_error());
+      *ok = false;
+    }
+  }
+
+  void ValidateAssignmentPattern(const ExpressionClassifier* classifier,
+                                 bool* ok) {
+    if (!classifier->is_valid_assignment_pattern()) {
+      ReportClassifierError(classifier->assignment_pattern_error());
+      *ok = false;
+    }
+  }
+
+  void ValidateFormalParameters(const ExpressionClassifier* classifier,
+                                LanguageMode language_mode,
+                                bool allow_duplicates, bool* ok) {
+    if (!allow_duplicates &&
+        !classifier->is_valid_formal_parameter_list_without_duplicates()) {
+      ReportClassifierError(classifier->duplicate_formal_parameter_error());
+      *ok = false;
+    } else if (is_strict(language_mode) &&
+               !classifier->is_valid_strict_mode_formal_parameters()) {
+      ReportClassifierError(classifier->strict_mode_formal_parameter_error());
+      *ok = false;
+    } else if (is_strong(language_mode) &&
+               !classifier->is_valid_strong_mode_formal_parameters()) {
+      ReportClassifierError(classifier->strong_mode_formal_parameter_error());
+      *ok = false;
+    }
+  }
+
+  void ValidateArrowFormalParameters(const ExpressionClassifier* classifier,
+                                     ExpressionT expr,
+                                     bool parenthesized_formals, bool* ok) {
+    if (classifier->is_valid_binding_pattern()) {
+      // A simple arrow formal parameter: IDENTIFIER => BODY.
+      if (!this->IsIdentifier(expr)) {
+        Traits::ReportMessageAt(scanner()->location(),
+                                MessageTemplate::kUnexpectedToken,
+                                Token::String(scanner()->current_token()));
+        *ok = false;
+      }
+    } else if (!classifier->is_valid_arrow_formal_parameters()) {
+      // If after parsing the expr, we see an error but the expression is
+      // neither a valid binding pattern nor a valid parenthesized formal
+      // parameter list, show the "arrow formal parameters" error if the formals
+      // started with a parenthesis, and the binding pattern error otherwise.
+      const ExpressionClassifier::Error& error =
+          parenthesized_formals ? classifier->arrow_formal_parameters_error()
+                                : classifier->binding_pattern_error();
+      ReportClassifierError(error);
+      *ok = false;
+    }
+  }
+
+  void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) {
+    if (!classifier->is_valid_let_pattern()) {
+      ReportClassifierError(classifier->let_pattern_error());
+      *ok = false;
+    }
+  }
+
+  void ExpressionUnexpectedToken(ExpressionClassifier* classifier) {
+    MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
+    const char* arg;
+    GetUnexpectedTokenMessage(peek(), &message, &arg);
+    classifier->RecordExpressionError(scanner()->peek_location(), message, arg);
+  }
+
+  void BindingPatternUnexpectedToken(ExpressionClassifier* classifier) {
+    MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
+    const char* arg;
+    GetUnexpectedTokenMessage(peek(), &message, &arg);
+    classifier->RecordBindingPatternError(scanner()->peek_location(), message,
+                                          arg);
+  }
+
+  void ArrowFormalParametersUnexpectedToken(ExpressionClassifier* classifier) {
+    MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
+    const char* arg;
+    GetUnexpectedTokenMessage(peek(), &message, &arg);
+    classifier->RecordArrowFormalParametersError(scanner()->peek_location(),
+                                                 message, arg);
+  }
+
+  void FormalParameterInitializerUnexpectedToken(
+      ExpressionClassifier* classifier) {
+    MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
+    const char* arg;
+    GetUnexpectedTokenMessage(peek(), &message, &arg);
+    classifier->RecordFormalParameterInitializerError(
+        scanner()->peek_location(), message, arg);
+  }
+
+  // Recursive descent functions:
+
+  // Parses an identifier that is valid for the current scope, in particular it
+  // fails on strict mode future reserved keywords in a strict scope. If
+  // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
+  // "arguments" as identifier even in strict mode (this is needed in cases like
+  // "var foo = eval;").
+  IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok);
+  IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
+                                         bool* ok);
+  // Parses an identifier or a strict mode future reserved word, and indicate
+  // whether it is strict mode future reserved. Allows passing in is_generator
+  // for the case of parsing the identifier in a function expression, where the
+  // relevant "is_generator" bit is of the function being parsed, not the
+  // containing
+  // function.
+  IdentifierT ParseIdentifierOrStrictReservedWord(bool is_generator,
+                                                  bool* is_strict_reserved,
+                                                  bool* ok);
+  IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
+                                                  bool* ok) {
+    return ParseIdentifierOrStrictReservedWord(this->is_generator(),
+                                               is_strict_reserved, ok);
+  }
+
+  IdentifierT ParseIdentifierName(bool* ok);
+  // Parses an identifier and determines whether or not it is 'get' or 'set'.
+  IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set,
+                                            bool* ok);
+
+
+  ExpressionT ParseRegExpLiteral(bool seen_equal,
+                                 ExpressionClassifier* classifier, bool* ok);
+
+  ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier,
+                                     bool* ok);
+  ExpressionT ParseExpression(bool accept_IN, bool* ok);
+  ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier,
+                              bool* ok);
+  ExpressionT ParseExpression(bool accept_IN, int flags,
+                              ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set,
+                                bool* is_static, bool* is_computed_name,
+                                bool* is_identifier, bool* is_escaped_keyword,
+                                ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok);
+  ObjectLiteralPropertyT ParsePropertyDefinition(
+      ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
+      bool is_static, bool* is_computed_name, bool* has_seen_constructor,
+      ExpressionClassifier* classifier, IdentifierT* name, bool* ok);
+  typename Traits::Type::ExpressionList ParseArguments(
+      Scanner::Location* first_spread_pos, ExpressionClassifier* classifier,
+      bool* ok);
+
+  enum AssignmentExpressionFlags {
+    kIsNormalAssignment = 0,
+    kIsPossiblePatternElement = 1 << 0,
+    kIsPossibleArrowFormals = 1 << 1
+  };
+
+  ExpressionT ParseAssignmentExpression(bool accept_IN, int flags,
+                                        ExpressionClassifier* classifier,
+                                        bool* ok);
+  ExpressionT ParseAssignmentExpression(bool accept_IN,
+                                        ExpressionClassifier* classifier,
+                                        bool* ok) {
+    return ParseAssignmentExpression(accept_IN, kIsNormalAssignment, classifier,
+                                     ok);
+  }
+  ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseConditionalExpression(bool accept_IN,
+                                         ExpressionClassifier* classifier,
+                                         bool* ok);
+  ExpressionT ParseBinaryExpression(int prec, bool accept_IN,
+                                    ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParsePostfixExpression(ExpressionClassifier* classifier,
+                                     bool* ok);
+  ExpressionT ParseLeftHandSideExpression(ExpressionClassifier* classifier,
+                                          bool* ok);
+  ExpressionT ParseMemberWithNewPrefixesExpression(
+      ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseMemberExpressionContinuation(
+      ExpressionT expression, ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseArrowFunctionLiteral(bool accept_IN,
+                                        const FormalParametersT& parameters,
+                                        const ExpressionClassifier& classifier,
+                                        bool* ok);
+  ExpressionT ParseTemplateLiteral(ExpressionT tag, int start,
+                                   ExpressionClassifier* classifier, bool* ok);
+  void AddTemplateExpression(ExpressionT);
+  ExpressionT ParseSuperExpression(bool is_new,
+                                   ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseNewTargetExpression(bool* ok);
+  ExpressionT ParseStrongInitializationExpression(
+      ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier,
+                                             bool* ok);
+
+  void ParseFormalParameter(FormalParametersT* parameters,
+                            ExpressionClassifier* classifier, bool* ok);
+  void ParseFormalParameterList(FormalParametersT* parameters,
+                                ExpressionClassifier* classifier, bool* ok);
+  void CheckArityRestrictions(
+      int param_count, FunctionLiteral::ArityRestriction arity_restriction,
+      bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok);
+
+  bool IsNextLetKeyword();
+
+  // Checks if the expression is a valid reference expression (e.g., on the
+  // left-hand side of assignments). Although ruled out by ECMA as early errors,
+  // we allow calls for web compatibility and rewrite them to a runtime throw.
+  ExpressionT CheckAndRewriteReferenceExpression(
+      ExpressionT expression, int beg_pos, int end_pos,
+      MessageTemplate::Template message, bool* ok);
+  ExpressionT ClassifyAndRewriteReferenceExpression(
+      ExpressionClassifier* classifier, ExpressionT expression, int beg_pos,
+      int end_pos, MessageTemplate::Template message,
+      ParseErrorType type = kSyntaxError);
+  ExpressionT CheckAndRewriteReferenceExpression(
+      ExpressionT expression, int beg_pos, int end_pos,
+      MessageTemplate::Template message, ParseErrorType type, bool* ok);
+
+  bool IsValidReferenceExpression(ExpressionT expression);
+
+  bool IsAssignableIdentifier(ExpressionT expression) {
+    if (!Traits::IsIdentifier(expression)) return false;
+    if (is_strict(language_mode()) &&
+        Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) {
+      return false;
+    }
+    if (is_strong(language_mode()) &&
+        Traits::IsUndefined(Traits::AsIdentifier(expression))) {
+      return false;
+    }
+    return true;
+  }
+
+  // Keep track of eval() calls since they disable all local variable
+  // optimizations. This checks if expression is an eval call, and if yes,
+  // forwards the information to scope.
+  void CheckPossibleEvalCall(ExpressionT expression, Scope* scope) {
+    if (Traits::IsIdentifier(expression) &&
+        Traits::IsEval(Traits::AsIdentifier(expression))) {
+      scope->DeclarationScope()->RecordEvalCall();
+      scope->RecordEvalCall();
+    }
+  }
+
+  // Used to validate property names in object literals and class literals
+  enum PropertyKind {
+    kAccessorProperty,
+    kValueProperty,
+    kMethodProperty
+  };
+
+  class ObjectLiteralCheckerBase {
+   public:
+    explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
+
+    virtual void CheckProperty(Token::Value property, PropertyKind type,
+                               bool is_static, bool is_generator, bool* ok) = 0;
+
+    virtual ~ObjectLiteralCheckerBase() {}
+
+   protected:
+    ParserBase* parser() const { return parser_; }
+    Scanner* scanner() const { return parser_->scanner(); }
+
+   private:
+    ParserBase* parser_;
+  };
+
+  // Validation per ES6 object literals.
+  class ObjectLiteralChecker : public ObjectLiteralCheckerBase {
+   public:
+    explicit ObjectLiteralChecker(ParserBase* parser)
+        : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {}
+
+    void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
+                       bool is_generator, bool* ok) override;
+
+   private:
+    bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); }
+
+    bool has_seen_proto_;
+  };
+
+  // Validation per ES6 class literals.
+  class ClassLiteralChecker : public ObjectLiteralCheckerBase {
+   public:
+    explicit ClassLiteralChecker(ParserBase* parser)
+        : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {}
+
+    void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
+                       bool is_generator, bool* ok) override;
+
+   private:
+    bool IsConstructor() {
+      return this->scanner()->LiteralMatches("constructor", 11);
+    }
+    bool IsPrototype() {
+      return this->scanner()->LiteralMatches("prototype", 9);
+    }
+
+    bool has_seen_constructor_;
+  };
+
+  // If true, the next (and immediately following) function literal is
+  // preceded by a parenthesis.
+  // Heuristically that means that the function will be called immediately,
+  // so never lazily compile it.
+  bool parenthesized_function_;
+
+  Scope* scope_;                   // Scope stack.
+  FunctionState* function_state_;  // Function state stack.
+  v8::Extension* extension_;
+  FuncNameInferrer* fni_;
+  AstValueFactory* ast_value_factory_;  // Not owned.
+  ParserRecorder* log_;
+  Mode mode_;
+  uintptr_t stack_limit_;
+
+ private:
+  Zone* zone_;
+
+  Scanner* scanner_;
+  bool stack_overflow_;
+
+  bool allow_lazy_;
+  bool allow_natives_;
+  bool allow_harmony_sloppy_;
+  bool allow_harmony_sloppy_function_;
+  bool allow_harmony_sloppy_let_;
+  bool allow_harmony_default_parameters_;
+  bool allow_harmony_destructuring_bind_;
+  bool allow_harmony_destructuring_assignment_;
+  bool allow_strong_mode_;
+  bool allow_legacy_const_;
+  bool allow_harmony_do_expressions_;
+  bool allow_harmony_function_name_;
+};
+
+
+template <class Traits>
+ParserBase<Traits>::FunctionState::FunctionState(
+    FunctionState** function_state_stack, Scope** scope_stack, Scope* scope,
+    FunctionKind kind, typename Traits::Type::Factory* factory)
+    : next_materialized_literal_index_(0),
+      expected_property_count_(0),
+      this_location_(Scanner::Location::invalid()),
+      return_location_(Scanner::Location::invalid()),
+      super_location_(Scanner::Location::invalid()),
+      kind_(kind),
+      generator_object_variable_(NULL),
+      function_state_stack_(function_state_stack),
+      outer_function_state_(*function_state_stack),
+      scope_stack_(scope_stack),
+      outer_scope_(*scope_stack),
+      factory_(factory) {
+  *scope_stack_ = scope;
+  *function_state_stack = this;
+}
+
+
+template <class Traits>
+ParserBase<Traits>::FunctionState::~FunctionState() {
+  *scope_stack_ = outer_scope_;
+  *function_state_stack_ = outer_function_state_;
+}
+
+
+template <class Traits>
+void ParserBase<Traits>::GetUnexpectedTokenMessage(
+    Token::Value token, MessageTemplate::Template* message, const char** arg,
+    MessageTemplate::Template default_) {
+  // Four of the tokens are treated specially
+  switch (token) {
+    case Token::EOS:
+      *message = MessageTemplate::kUnexpectedEOS;
+      *arg = nullptr;
+      break;
+    case Token::SMI:
+    case Token::NUMBER:
+      *message = MessageTemplate::kUnexpectedTokenNumber;
+      *arg = nullptr;
+      break;
+    case Token::STRING:
+      *message = MessageTemplate::kUnexpectedTokenString;
+      *arg = nullptr;
+      break;
+    case Token::IDENTIFIER:
+      *message = MessageTemplate::kUnexpectedTokenIdentifier;
+      *arg = nullptr;
+      break;
+    case Token::FUTURE_RESERVED_WORD:
+      *message = MessageTemplate::kUnexpectedReserved;
+      *arg = nullptr;
+      break;
+    case Token::LET:
+    case Token::STATIC:
+    case Token::YIELD:
+    case Token::FUTURE_STRICT_RESERVED_WORD:
+      *message = is_strict(language_mode())
+                     ? MessageTemplate::kUnexpectedStrictReserved
+                     : MessageTemplate::kUnexpectedTokenIdentifier;
+      *arg = nullptr;
+      break;
+    case Token::TEMPLATE_SPAN:
+    case Token::TEMPLATE_TAIL:
+      *message = MessageTemplate::kUnexpectedTemplateString;
+      *arg = nullptr;
+      break;
+    case Token::ESCAPED_STRICT_RESERVED_WORD:
+    case Token::ESCAPED_KEYWORD:
+      *message = MessageTemplate::kInvalidEscapedReservedWord;
+      *arg = nullptr;
+      break;
+    default:
+      const char* name = Token::String(token);
+      DCHECK(name != NULL);
+      *arg = name;
+      break;
+  }
+}
+
+
+template <class Traits>
+void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
+  return ReportUnexpectedTokenAt(scanner_->location(), token);
+}
+
+
+template <class Traits>
+void ParserBase<Traits>::ReportUnexpectedTokenAt(
+    Scanner::Location source_location, Token::Value token,
+    MessageTemplate::Template message) {
+  const char* arg;
+  GetUnexpectedTokenMessage(token, &message, &arg);
+  Traits::ReportMessageAt(source_location, message, arg);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
+    AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) {
+  ExpressionClassifier classifier;
+  auto result = ParseAndClassifyIdentifier(&classifier, ok);
+  if (!*ok) return Traits::EmptyIdentifier();
+
+  if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) {
+    ValidateAssignmentPattern(&classifier, ok);
+    if (!*ok) return Traits::EmptyIdentifier();
+    ValidateBindingPattern(&classifier, ok);
+    if (!*ok) return Traits::EmptyIdentifier();
+  }
+
+  return result;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::IdentifierT
+ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
+                                               bool* ok) {
+  Token::Value next = Next();
+  if (next == Token::IDENTIFIER) {
+    IdentifierT name = this->GetSymbol(scanner());
+    // When this function is used to read a formal parameter, we don't always
+    // know whether the function is going to be strict or sloppy.  Indeed for
+    // arrow functions we don't always know that the identifier we are reading
+    // is actually a formal parameter.  Therefore besides the errors that we
+    // must detect because we know we're in strict mode, we also record any
+    // error that we might make in the future once we know the language mode.
+    if (this->IsEval(name)) {
+      classifier->RecordStrictModeFormalParameterError(
+          scanner()->location(), MessageTemplate::kStrictEvalArguments);
+      if (is_strict(language_mode())) {
+        classifier->RecordBindingPatternError(
+            scanner()->location(), MessageTemplate::kStrictEvalArguments);
+      }
+    }
+    if (this->IsArguments(name)) {
+      scope_->RecordArgumentsUsage();
+      classifier->RecordStrictModeFormalParameterError(
+          scanner()->location(), MessageTemplate::kStrictEvalArguments);
+      if (is_strict(language_mode())) {
+        classifier->RecordBindingPatternError(
+            scanner()->location(), MessageTemplate::kStrictEvalArguments);
+      }
+      if (is_strong(language_mode())) {
+        classifier->RecordExpressionError(scanner()->location(),
+                                          MessageTemplate::kStrongArguments);
+      }
+    }
+    if (this->IsUndefined(name)) {
+      classifier->RecordStrongModeFormalParameterError(
+          scanner()->location(), MessageTemplate::kStrongUndefined);
+      if (is_strong(language_mode())) {
+        // TODO(dslomov): allow 'undefined' in nested patterns.
+        classifier->RecordBindingPatternError(
+            scanner()->location(), MessageTemplate::kStrongUndefined);
+        classifier->RecordAssignmentPatternError(
+            scanner()->location(), MessageTemplate::kStrongUndefined);
+      }
+    }
+
+    if (classifier->duplicate_finder() != nullptr &&
+        scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
+      classifier->RecordDuplicateFormalParameterError(scanner()->location());
+    }
+    return name;
+  } else if (is_sloppy(language_mode()) &&
+             (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+              next == Token::ESCAPED_STRICT_RESERVED_WORD ||
+              next == Token::LET || next == Token::STATIC ||
+              (next == Token::YIELD && !is_generator()))) {
+    classifier->RecordStrictModeFormalParameterError(
+        scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
+    if (next == Token::ESCAPED_STRICT_RESERVED_WORD &&
+        is_strict(language_mode())) {
+      ReportUnexpectedToken(next);
+      *ok = false;
+      return Traits::EmptyIdentifier();
+    }
+    if (next == Token::LET) {
+      classifier->RecordLetPatternError(scanner()->location(),
+                                        MessageTemplate::kLetInLexicalBinding);
+    }
+    return this->GetSymbol(scanner());
+  } else {
+    this->ReportUnexpectedToken(next);
+    *ok = false;
+    return Traits::EmptyIdentifier();
+  }
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::IdentifierT
+ParserBase<Traits>::ParseIdentifierOrStrictReservedWord(
+    bool is_generator, bool* is_strict_reserved, bool* ok) {
+  Token::Value next = Next();
+  if (next == Token::IDENTIFIER) {
+    *is_strict_reserved = false;
+  } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
+             next == Token::STATIC || (next == Token::YIELD && !is_generator)) {
+    *is_strict_reserved = true;
+  } else {
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return Traits::EmptyIdentifier();
+  }
+
+  IdentifierT name = this->GetSymbol(scanner());
+  if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
+  return name;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::IdentifierT
+ParserBase<Traits>::ParseIdentifierName(bool* ok) {
+  Token::Value next = Next();
+  if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
+      next != Token::LET && next != Token::STATIC && next != Token::YIELD &&
+      next != Token::FUTURE_STRICT_RESERVED_WORD &&
+      next != Token::ESCAPED_KEYWORD &&
+      next != Token::ESCAPED_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
+    this->ReportUnexpectedToken(next);
+    *ok = false;
+    return Traits::EmptyIdentifier();
+  }
+
+  IdentifierT name = this->GetSymbol(scanner());
+  if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
+  return name;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::IdentifierT
+ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
+                                                  bool* is_set,
+                                                  bool* ok) {
+  IdentifierT result = ParseIdentifierName(ok);
+  if (!*ok) return Traits::EmptyIdentifier();
+  scanner()->IsGetOrSet(is_get, is_set);
+  return result;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
+    bool seen_equal, ExpressionClassifier* classifier, bool* ok) {
+  int pos = peek_position();
+  if (!scanner()->ScanRegExpPattern(seen_equal)) {
+    Next();
+    ReportMessage(MessageTemplate::kUnterminatedRegExp);
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+
+  int literal_index = function_state_->NextMaterializedLiteralIndex();
+
+  IdentifierT js_pattern = this->GetNextSymbol(scanner());
+  Maybe<RegExp::Flags> flags = scanner()->ScanRegExpFlags();
+  if (flags.IsNothing()) {
+    Next();
+    ReportMessage(MessageTemplate::kMalformedRegExpFlags);
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+  int js_flags = flags.FromJust();
+  Next();
+  return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index,
+                                     is_strong(language_mode()), pos);
+}
+
+
+#define CHECK_OK  ok); \
+  if (!*ok) return this->EmptyExpression(); \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+// Used in functions where the return type is not ExpressionT.
+#define CHECK_OK_CUSTOM(x) ok); \
+  if (!*ok) return this->x(); \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
+                                           bool* ok) {
+  // PrimaryExpression ::
+  //   'this'
+  //   'null'
+  //   'true'
+  //   'false'
+  //   Identifier
+  //   Number
+  //   String
+  //   ArrayLiteral
+  //   ObjectLiteral
+  //   RegExpLiteral
+  //   ClassLiteral
+  //   '(' Expression ')'
+  //   TemplateLiteral
+  //   do Block
+
+  int beg_pos = peek_position();
+  switch (peek()) {
+    case Token::THIS: {
+      BindingPatternUnexpectedToken(classifier);
+      Consume(Token::THIS);
+      if (FLAG_strong_this && is_strong(language_mode())) {
+        // Constructors' usages of 'this' in strong mode are parsed separately.
+        // TODO(rossberg): this does not work with arrow functions yet.
+        if (IsClassConstructor(function_state_->kind())) {
+          ReportMessage(MessageTemplate::kStrongConstructorThis);
+          *ok = false;
+          return this->EmptyExpression();
+        }
+      }
+      return this->ThisExpression(scope_, factory(), beg_pos);
+    }
+
+    case Token::NULL_LITERAL:
+    case Token::TRUE_LITERAL:
+    case Token::FALSE_LITERAL:
+      BindingPatternUnexpectedToken(classifier);
+      return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
+    case Token::SMI:
+    case Token::NUMBER:
+      classifier->RecordBindingPatternError(
+          scanner()->peek_location(), MessageTemplate::kUnexpectedTokenNumber);
+      return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
+
+    case Token::IDENTIFIER:
+    case Token::LET:
+    case Token::STATIC:
+    case Token::YIELD:
+    case Token::ESCAPED_STRICT_RESERVED_WORD:
+    case Token::FUTURE_STRICT_RESERVED_WORD: {
+      // Using eval or arguments in this context is OK even in strict mode.
+      IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK);
+      return this->ExpressionFromIdentifier(
+          name, beg_pos, scanner()->location().end_pos, scope_, factory());
+    }
+
+    case Token::STRING: {
+      classifier->RecordBindingPatternError(
+          scanner()->peek_location(), MessageTemplate::kUnexpectedTokenString);
+      Consume(Token::STRING);
+      return this->ExpressionFromString(beg_pos, scanner(), factory());
+    }
+
+    case Token::ASSIGN_DIV:
+      classifier->RecordBindingPatternError(
+          scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp);
+      return this->ParseRegExpLiteral(true, classifier, ok);
+
+    case Token::DIV:
+      classifier->RecordBindingPatternError(
+          scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp);
+      return this->ParseRegExpLiteral(false, classifier, ok);
+
+    case Token::LBRACK:
+      if (!allow_harmony_destructuring_bind()) {
+        BindingPatternUnexpectedToken(classifier);
+      }
+      return this->ParseArrayLiteral(classifier, ok);
+
+    case Token::LBRACE:
+      if (!allow_harmony_destructuring_bind()) {
+        BindingPatternUnexpectedToken(classifier);
+      }
+      return this->ParseObjectLiteral(classifier, ok);
+
+    case Token::LPAREN: {
+      // Arrow function formal parameters are either a single identifier or a
+      // list of BindingPattern productions enclosed in parentheses.
+      // Parentheses are not valid on the LHS of a BindingPattern, so we use the
+      // is_valid_binding_pattern() check to detect multiple levels of
+      // parenthesization.
+      if (!classifier->is_valid_binding_pattern()) {
+        ArrowFormalParametersUnexpectedToken(classifier);
+      }
+      BindingPatternUnexpectedToken(classifier);
+      Consume(Token::LPAREN);
+      if (Check(Token::RPAREN)) {
+        // ()=>x.  The continuation that looks for the => is in
+        // ParseAssignmentExpression.
+        classifier->RecordExpressionError(scanner()->location(),
+                                          MessageTemplate::kUnexpectedToken,
+                                          Token::String(Token::RPAREN));
+        classifier->RecordBindingPatternError(scanner()->location(),
+                                              MessageTemplate::kUnexpectedToken,
+                                              Token::String(Token::RPAREN));
+        return factory()->NewEmptyParentheses(beg_pos);
+      } else if (Check(Token::ELLIPSIS)) {
+        // (...x)=>x.  The continuation that looks for the => is in
+        // ParseAssignmentExpression.
+        int ellipsis_pos = position();
+        classifier->RecordExpressionError(scanner()->location(),
+                                          MessageTemplate::kUnexpectedToken,
+                                          Token::String(Token::ELLIPSIS));
+        classifier->RecordNonSimpleParameter();
+        ExpressionT expr =
+            this->ParseAssignmentExpression(true, classifier, CHECK_OK);
+        if (peek() == Token::COMMA) {
+          ReportMessageAt(scanner()->peek_location(),
+                          MessageTemplate::kParamAfterRest);
+          *ok = false;
+          return this->EmptyExpression();
+        }
+        Expect(Token::RPAREN, CHECK_OK);
+        return factory()->NewSpread(expr, ellipsis_pos);
+      }
+      // Heuristically try to detect immediately called functions before
+      // seeing the call parentheses.
+      parenthesized_function_ = (peek() == Token::FUNCTION);
+      ExpressionT expr = this->ParseExpression(true, kIsPossibleArrowFormals,
+                                               classifier, CHECK_OK);
+      Expect(Token::RPAREN, CHECK_OK);
+      if (peek() != Token::ARROW) {
+        expr->set_is_parenthesized();
+      }
+      return expr;
+    }
+
+    case Token::CLASS: {
+      BindingPatternUnexpectedToken(classifier);
+      Consume(Token::CLASS);
+      if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
+        ReportMessage(MessageTemplate::kSloppyLexical);
+        *ok = false;
+        return this->EmptyExpression();
+      }
+      int class_token_position = position();
+      IdentifierT name = this->EmptyIdentifier();
+      bool is_strict_reserved_name = false;
+      Scanner::Location class_name_location = Scanner::Location::invalid();
+      if (peek_any_identifier()) {
+        name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
+                                                   CHECK_OK);
+        class_name_location = scanner()->location();
+      }
+      return this->ParseClassLiteral(name, class_name_location,
+                                     is_strict_reserved_name,
+                                     class_token_position, ok);
+    }
+
+    case Token::TEMPLATE_SPAN:
+    case Token::TEMPLATE_TAIL:
+      classifier->RecordBindingPatternError(
+          scanner()->peek_location(),
+          MessageTemplate::kUnexpectedTemplateString);
+      return this->ParseTemplateLiteral(Traits::NoTemplateTag(), beg_pos,
+                                        classifier, ok);
+
+    case Token::MOD:
+      if (allow_natives() || extension_ != NULL) {
+        BindingPatternUnexpectedToken(classifier);
+        return this->ParseV8Intrinsic(ok);
+      }
+      break;
+
+    case Token::DO:
+      if (allow_harmony_do_expressions()) {
+        BindingPatternUnexpectedToken(classifier);
+        return Traits::ParseDoExpression(ok);
+      }
+      break;
+
+    default:
+      break;
+  }
+
+  ReportUnexpectedToken(Next());
+  *ok = false;
+  return this->EmptyExpression();
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
+    bool accept_IN, bool* ok) {
+  ExpressionClassifier classifier;
+  ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK);
+  result = Traits::RewriteNonPattern(result, &classifier, CHECK_OK);
+  return result;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
+    bool accept_IN, ExpressionClassifier* classifier, bool* ok) {
+  return ParseExpression(accept_IN, kIsNormalAssignment, classifier, ok);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
+    bool accept_IN, int flags, ExpressionClassifier* classifier, bool* ok) {
+  // Expression ::
+  //   AssignmentExpression
+  //   Expression ',' AssignmentExpression
+
+  ExpressionClassifier binding_classifier;
+  ExpressionT result = this->ParseAssignmentExpression(
+      accept_IN, flags, &binding_classifier, CHECK_OK);
+  classifier->Accumulate(binding_classifier,
+                         ExpressionClassifier::AllProductions);
+  bool is_simple_parameter_list = this->IsIdentifier(result);
+  bool seen_rest = false;
+  while (peek() == Token::COMMA) {
+    if (seen_rest) {
+      // At this point the production can't possibly be valid, but we don't know
+      // which error to signal.
+      classifier->RecordArrowFormalParametersError(
+          scanner()->peek_location(), MessageTemplate::kParamAfterRest);
+    }
+    Consume(Token::COMMA);
+    bool is_rest = false;
+    if (peek() == Token::ELLIPSIS) {
+      // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
+      // as the formal parameters of'(x, y, ...z) => foo', and is not itself a
+      // valid expression or binding pattern.
+      ExpressionUnexpectedToken(classifier);
+      BindingPatternUnexpectedToken(classifier);
+      Consume(Token::ELLIPSIS);
+      seen_rest = is_rest = true;
+    }
+    int pos = position();
+    ExpressionT right = this->ParseAssignmentExpression(
+        accept_IN, flags, &binding_classifier, CHECK_OK);
+    if (is_rest) right = factory()->NewSpread(right, pos);
+    is_simple_parameter_list =
+        is_simple_parameter_list && this->IsIdentifier(right);
+    classifier->Accumulate(binding_classifier,
+                           ExpressionClassifier::AllProductions);
+    result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
+  }
+  if (!is_simple_parameter_list || seen_rest) {
+    classifier->RecordNonSimpleParameter();
+  }
+
+  return result;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
+    ExpressionClassifier* classifier, bool* ok) {
+  // ArrayLiteral ::
+  //   '[' Expression? (',' Expression?)* ']'
+
+  int pos = peek_position();
+  typename Traits::Type::ExpressionList values =
+      this->NewExpressionList(4, zone_);
+  int first_spread_index = -1;
+  Expect(Token::LBRACK, CHECK_OK);
+  while (peek() != Token::RBRACK) {
+    ExpressionT elem = this->EmptyExpression();
+    if (peek() == Token::COMMA) {
+      if (is_strong(language_mode())) {
+        ReportMessageAt(scanner()->peek_location(),
+                        MessageTemplate::kStrongEllision);
+        *ok = false;
+        return this->EmptyExpression();
+      }
+      elem = this->GetLiteralTheHole(peek_position(), factory());
+    } else if (peek() == Token::ELLIPSIS) {
+      int start_pos = peek_position();
+      Consume(Token::ELLIPSIS);
+      ExpressionT argument =
+          this->ParseAssignmentExpression(true, classifier, CHECK_OK);
+      elem = factory()->NewSpread(argument, start_pos);
+
+      if (first_spread_index < 0) {
+        first_spread_index = values->length();
+      }
+
+      if (argument->IsAssignment()) {
+        classifier->RecordPatternError(
+            Scanner::Location(start_pos, scanner()->location().end_pos),
+            MessageTemplate::kInvalidDestructuringTarget);
+      } else {
+        CheckDestructuringElement(argument, classifier, start_pos,
+                                  scanner()->location().end_pos);
+      }
+
+      if (peek() == Token::COMMA) {
+        classifier->RecordPatternError(
+            Scanner::Location(start_pos, scanner()->location().end_pos),
+            MessageTemplate::kElementAfterRest);
+      }
+    } else {
+      elem = this->ParseAssignmentExpression(true, kIsPossiblePatternElement,
+                                             classifier, CHECK_OK);
+    }
+    values->Add(elem, zone_);
+    if (peek() != Token::RBRACK) {
+      Expect(Token::COMMA, CHECK_OK);
+    }
+  }
+  Expect(Token::RBRACK, CHECK_OK);
+
+  // Update the scope information before the pre-parsing bailout.
+  int literal_index = function_state_->NextMaterializedLiteralIndex();
+
+  return factory()->NewArrayLiteral(values, first_spread_index, literal_index,
+                                    is_strong(language_mode()), pos);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
+    IdentifierT* name, bool* is_get, bool* is_set, bool* is_static,
+    bool* is_computed_name, bool* is_identifier, bool* is_escaped_keyword,
+    ExpressionClassifier* classifier, bool* ok) {
+  Token::Value token = peek();
+  int pos = peek_position();
+
+  // For non computed property names we normalize the name a bit:
+  //
+  //   "12" -> 12
+  //   12.3 -> "12.3"
+  //   12.30 -> "12.3"
+  //   identifier -> "identifier"
+  //
+  // This is important because we use the property name as a key in a hash
+  // table when we compute constant properties.
+  switch (token) {
+    case Token::STRING:
+      Consume(Token::STRING);
+      *name = this->GetSymbol(scanner());
+      break;
+
+    case Token::SMI:
+      Consume(Token::SMI);
+      *name = this->GetNumberAsSymbol(scanner());
+      break;
+
+    case Token::NUMBER:
+      Consume(Token::NUMBER);
+      *name = this->GetNumberAsSymbol(scanner());
+      break;
+
+    case Token::LBRACK: {
+      *is_computed_name = true;
+      Consume(Token::LBRACK);
+      ExpressionClassifier computed_name_classifier;
+      ExpressionT expression =
+          ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK);
+      expression = Traits::RewriteNonPattern(
+          expression, &computed_name_classifier, CHECK_OK);
+      classifier->Accumulate(computed_name_classifier,
+                             ExpressionClassifier::ExpressionProductions);
+      Expect(Token::RBRACK, CHECK_OK);
+      return expression;
+    }
+
+    case Token::ESCAPED_KEYWORD:
+      *is_escaped_keyword = true;
+      *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK);
+      break;
+
+    case Token::STATIC:
+      *is_static = true;
+
+    // Fall through.
+    default:
+      *is_identifier = true;
+      *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK);
+      break;
+  }
+
+  uint32_t index;
+  return this->IsArrayIndex(*name, &index)
+             ? factory()->NewNumberLiteral(index, pos)
+             : factory()->NewStringLiteral(*name, pos);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ObjectLiteralPropertyT
+ParserBase<Traits>::ParsePropertyDefinition(
+    ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
+    bool is_static, bool* is_computed_name, bool* has_seen_constructor,
+    ExpressionClassifier* classifier, IdentifierT* name, bool* ok) {
+  DCHECK(!in_class || is_static || has_seen_constructor != nullptr);
+  ExpressionT value = this->EmptyExpression();
+  bool is_get = false;
+  bool is_set = false;
+  bool name_is_static = false;
+  bool is_generator = Check(Token::MUL);
+
+  Token::Value name_token = peek();
+  int next_beg_pos = scanner()->peek_location().beg_pos;
+  int next_end_pos = scanner()->peek_location().end_pos;
+  bool is_identifier = false;
+  bool is_escaped_keyword = false;
+  ExpressionT name_expression = ParsePropertyName(
+      name, &is_get, &is_set, &name_is_static, is_computed_name, &is_identifier,
+      &is_escaped_keyword, classifier,
+      CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+  if (fni_ != nullptr && !*is_computed_name) {
+    this->PushLiteralName(fni_, *name);
+  }
+
+  bool escaped_static =
+      is_escaped_keyword &&
+      scanner()->is_literal_contextual_keyword(CStrVector("static"));
+
+  if (!in_class && !is_generator) {
+    DCHECK(!is_static);
+
+    if (peek() == Token::COLON) {
+      // PropertyDefinition
+      //    PropertyName ':' AssignmentExpression
+      if (!*is_computed_name) {
+        checker->CheckProperty(name_token, kValueProperty, false, false,
+                               CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+      }
+      Consume(Token::COLON);
+      value = this->ParseAssignmentExpression(
+          true, kIsPossiblePatternElement, classifier,
+          CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+      return factory()->NewObjectLiteralProperty(name_expression, value, false,
+                                                 *is_computed_name);
+    }
+
+    if ((is_identifier || is_escaped_keyword) &&
+        (peek() == Token::COMMA || peek() == Token::RBRACE ||
+         peek() == Token::ASSIGN)) {
+      // PropertyDefinition
+      //    IdentifierReference
+      //    CoverInitializedName
+      //
+      // CoverInitializedName
+      //    IdentifierReference Initializer?
+      if (!Token::IsIdentifier(name_token, language_mode(),
+                               this->is_generator())) {
+        if (!escaped_static) {
+          ReportUnexpectedTokenAt(scanner()->location(), name_token);
+          *ok = false;
+          return this->EmptyObjectLiteralProperty();
+        }
+      }
+      if (classifier->duplicate_finder() != nullptr &&
+          scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
+        classifier->RecordDuplicateFormalParameterError(scanner()->location());
+      }
+      if (name_token == Token::LET) {
+        classifier->RecordLetPatternError(
+            scanner()->location(), MessageTemplate::kLetInLexicalBinding);
+      }
+
+      ExpressionT lhs = this->ExpressionFromIdentifier(
+          *name, next_beg_pos, next_end_pos, scope_, factory());
+      CheckDestructuringElement(lhs, classifier, next_beg_pos, next_end_pos);
+
+      if (peek() == Token::ASSIGN) {
+        Consume(Token::ASSIGN);
+        ExpressionClassifier rhs_classifier;
+        ExpressionT rhs = this->ParseAssignmentExpression(
+            true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+        rhs = Traits::RewriteNonPattern(
+            rhs, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+        classifier->Accumulate(rhs_classifier,
+                               ExpressionClassifier::ExpressionProductions);
+        value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
+                                         RelocInfo::kNoPosition);
+        classifier->RecordCoverInitializedNameError(
+            Scanner::Location(next_beg_pos, scanner()->location().end_pos),
+            MessageTemplate::kInvalidCoverInitializedName);
+      } else {
+        value = lhs;
+      }
+
+      return factory()->NewObjectLiteralProperty(
+          name_expression, value, ObjectLiteralProperty::COMPUTED, false,
+          false);
+    }
+  }
+
+  if (in_class && escaped_static && !is_static) {
+    ReportUnexpectedTokenAt(scanner()->location(), name_token);
+    *ok = false;
+    return this->EmptyObjectLiteralProperty();
+  }
+
+  // Method definitions are never valid in patterns.
+  classifier->RecordPatternError(
+      Scanner::Location(next_beg_pos, scanner()->location().end_pos),
+      MessageTemplate::kInvalidDestructuringTarget);
+
+  if (is_generator || peek() == Token::LPAREN) {
+    // MethodDefinition
+    //    PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
+    //    '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
+    if (!*is_computed_name) {
+      checker->CheckProperty(name_token, kMethodProperty, is_static,
+                             is_generator,
+                             CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    }
+
+    FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod
+                                     : FunctionKind::kConciseMethod;
+
+    if (in_class && !is_static && this->IsConstructor(*name)) {
+      *has_seen_constructor = true;
+      kind = has_extends ? FunctionKind::kSubclassConstructor
+                         : FunctionKind::kBaseConstructor;
+    }
+
+    if (!in_class) kind = WithObjectLiteralBit(kind);
+
+    value = this->ParseFunctionLiteral(
+        *name, scanner()->location(), kSkipFunctionNameCheck, kind,
+        RelocInfo::kNoPosition, FunctionLiteral::kAnonymousExpression,
+        FunctionLiteral::kNormalArity, language_mode(),
+        CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+    return factory()->NewObjectLiteralProperty(name_expression, value,
+                                               ObjectLiteralProperty::COMPUTED,
+                                               is_static, *is_computed_name);
+  }
+
+  if (in_class && name_is_static && !is_static) {
+    // ClassElement (static)
+    //    'static' MethodDefinition
+    *name = this->EmptyIdentifier();
+    ObjectLiteralPropertyT property = ParsePropertyDefinition(
+        checker, true, has_extends, true, is_computed_name, nullptr, classifier,
+        name, ok);
+    property = Traits::RewriteNonPatternObjectLiteralProperty(property,
+                                                              classifier, ok);
+    return property;
+  }
+
+  if (is_get || is_set) {
+    // MethodDefinition (Accessors)
+    //    get PropertyName '(' ')' '{' FunctionBody '}'
+    //    set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}'
+    *name = this->EmptyIdentifier();
+    bool dont_care = false;
+    name_token = peek();
+
+    name_expression = ParsePropertyName(
+        name, &dont_care, &dont_care, &dont_care, is_computed_name, &dont_care,
+        &dont_care, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+    if (!*is_computed_name) {
+      checker->CheckProperty(name_token, kAccessorProperty, is_static,
+                             is_generator,
+                             CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    }
+
+    FunctionKind kind = FunctionKind::kAccessorFunction;
+    if (!in_class) kind = WithObjectLiteralBit(kind);
+    typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
+        *name, scanner()->location(), kSkipFunctionNameCheck, kind,
+        RelocInfo::kNoPosition, FunctionLiteral::kAnonymousExpression,
+        is_get ? FunctionLiteral::kGetterArity : FunctionLiteral::kSetterArity,
+        language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+    // Make sure the name expression is a string since we need a Name for
+    // Runtime_DefineAccessorPropertyUnchecked and since we can determine this
+    // statically we can skip the extra runtime check.
+    if (!*is_computed_name) {
+      name_expression =
+          factory()->NewStringLiteral(*name, name_expression->position());
+    }
+
+    return factory()->NewObjectLiteralProperty(
+        name_expression, value,
+        is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER,
+        is_static, *is_computed_name);
+  }
+
+  Token::Value next = Next();
+  ReportUnexpectedToken(next);
+  *ok = false;
+  return this->EmptyObjectLiteralProperty();
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
+    ExpressionClassifier* classifier, bool* ok) {
+  // ObjectLiteral ::
+  // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
+
+  int pos = peek_position();
+  typename Traits::Type::PropertyList properties =
+      this->NewPropertyList(4, zone_);
+  int number_of_boilerplate_properties = 0;
+  bool has_function = false;
+  bool has_computed_names = false;
+  ObjectLiteralChecker checker(this);
+
+  Expect(Token::LBRACE, CHECK_OK);
+
+  while (peek() != Token::RBRACE) {
+    FuncNameInferrer::State fni_state(fni_);
+
+    const bool in_class = false;
+    const bool is_static = false;
+    const bool has_extends = false;
+    bool is_computed_name = false;
+    IdentifierT name = this->EmptyIdentifier();
+    ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
+        &checker, in_class, has_extends, is_static, &is_computed_name, NULL,
+        classifier, &name, CHECK_OK);
+
+    if (is_computed_name) {
+      has_computed_names = true;
+    }
+
+    // Mark top-level object literals that contain function literals and
+    // pretenure the literal so it can be added as a constant function
+    // property. (Parser only.)
+    this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property,
+                                                          &has_function);
+
+    // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
+    if (!has_computed_names && this->IsBoilerplateProperty(property)) {
+      number_of_boilerplate_properties++;
+    }
+    properties->Add(property, zone());
+
+    if (peek() != Token::RBRACE) {
+      // Need {} because of the CHECK_OK macro.
+      Expect(Token::COMMA, CHECK_OK);
+    }
+
+    if (fni_ != nullptr) fni_->Infer();
+
+    if (allow_harmony_function_name()) {
+      Traits::SetFunctionNameFromPropertyName(property, name);
+    }
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+
+  // Computation of literal_index must happen before pre parse bailout.
+  int literal_index = function_state_->NextMaterializedLiteralIndex();
+
+  return factory()->NewObjectLiteral(properties,
+                                     literal_index,
+                                     number_of_boilerplate_properties,
+                                     has_function,
+                                     is_strong(language_mode()),
+                                     pos);
+}
+
+
+template <class Traits>
+typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
+    Scanner::Location* first_spread_arg_loc, ExpressionClassifier* classifier,
+    bool* ok) {
+  // Arguments ::
+  //   '(' (AssignmentExpression)*[','] ')'
+
+  Scanner::Location spread_arg = Scanner::Location::invalid();
+  typename Traits::Type::ExpressionList result =
+      this->NewExpressionList(4, zone_);
+  Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
+  bool done = (peek() == Token::RPAREN);
+  bool was_unspread = false;
+  int unspread_sequences_count = 0;
+  while (!done) {
+    int start_pos = peek_position();
+    bool is_spread = Check(Token::ELLIPSIS);
+
+    ExpressionT argument = this->ParseAssignmentExpression(
+        true, classifier, CHECK_OK_CUSTOM(NullExpressionList));
+    argument = Traits::RewriteNonPattern(argument, classifier,
+                                         CHECK_OK_CUSTOM(NullExpressionList));
+    if (is_spread) {
+      if (!spread_arg.IsValid()) {
+        spread_arg.beg_pos = start_pos;
+        spread_arg.end_pos = peek_position();
+      }
+      argument = factory()->NewSpread(argument, start_pos);
+    }
+    result->Add(argument, zone_);
+
+    // unspread_sequences_count is the number of sequences of parameters which
+    // are not prefixed with a spread '...' operator.
+    if (is_spread) {
+      was_unspread = false;
+    } else if (!was_unspread) {
+      was_unspread = true;
+      unspread_sequences_count++;
+    }
+
+    if (result->length() > Code::kMaxArguments) {
+      ReportMessage(MessageTemplate::kTooManyArguments);
+      *ok = false;
+      return this->NullExpressionList();
+    }
+    done = (peek() != Token::COMMA);
+    if (!done) {
+      Next();
+    }
+  }
+  Scanner::Location location = scanner_->location();
+  if (Token::RPAREN != Next()) {
+    ReportMessageAt(location, MessageTemplate::kUnterminatedArgList);
+    *ok = false;
+    return this->NullExpressionList();
+  }
+  *first_spread_arg_loc = spread_arg;
+
+  if (spread_arg.IsValid()) {
+    // Unspread parameter sequences are translated into array literals in the
+    // parser. Ensure that the number of materialized literals matches between
+    // the parser and preparser
+    Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count);
+  }
+
+  return result;
+}
+
+// Precedence = 2
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, int flags,
+                                              ExpressionClassifier* classifier,
+                                              bool* ok) {
+  // AssignmentExpression ::
+  //   ConditionalExpression
+  //   ArrowFunction
+  //   YieldExpression
+  //   LeftHandSideExpression AssignmentOperator AssignmentExpression
+  bool maybe_pattern_element = flags & kIsPossiblePatternElement;
+  bool maybe_arrow_formals = flags & kIsPossibleArrowFormals;
+  bool is_destructuring_assignment = false;
+  int lhs_beg_pos = peek_position();
+
+  if (peek() == Token::YIELD && is_generator()) {
+    return this->ParseYieldExpression(classifier, ok);
+  }
+
+  FuncNameInferrer::State fni_state(fni_);
+  ParserBase<Traits>::Checkpoint checkpoint(this);
+  ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder());
+  bool parenthesized_formals = peek() == Token::LPAREN;
+  if (!parenthesized_formals) {
+    ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier);
+  }
+  ExpressionT expression = this->ParseConditionalExpression(
+      accept_IN, &arrow_formals_classifier, CHECK_OK);
+  if (peek() == Token::ARROW) {
+    BindingPatternUnexpectedToken(classifier);
+    ValidateArrowFormalParameters(&arrow_formals_classifier, expression,
+                                  parenthesized_formals, CHECK_OK);
+    Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos);
+    Scope* scope =
+        this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
+    // Because the arrow's parameters were parsed in the outer scope, any
+    // usage flags that might have been triggered there need to be copied
+    // to the arrow scope.
+    scope_->PropagateUsageFlagsToScope(scope);
+    FormalParametersT parameters(scope);
+    if (!arrow_formals_classifier.is_simple_parameter_list()) {
+      scope->SetHasNonSimpleParameters();
+      parameters.is_simple = false;
+    }
+
+    checkpoint.Restore(&parameters.materialized_literals_count);
+
+    scope->set_start_position(lhs_beg_pos);
+    Scanner::Location duplicate_loc = Scanner::Location::invalid();
+    this->ParseArrowFunctionFormalParameterList(&parameters, expression, loc,
+                                                &duplicate_loc, CHECK_OK);
+    if (duplicate_loc.IsValid()) {
+      arrow_formals_classifier.RecordDuplicateFormalParameterError(
+          duplicate_loc);
+    }
+    expression = this->ParseArrowFunctionLiteral(
+        accept_IN, parameters, arrow_formals_classifier, CHECK_OK);
+    if (maybe_pattern_element) {
+      classifier->RecordPatternError(
+          Scanner::Location(lhs_beg_pos, scanner()->location().end_pos),
+          MessageTemplate::kInvalidDestructuringTarget);
+    }
+
+    if (fni_ != nullptr) fni_->Infer();
+
+    return expression;
+  }
+
+  if (this->IsValidReferenceExpression(expression)) {
+    arrow_formals_classifier.ForgiveAssignmentPatternError();
+  }
+
+  // "expression" was not itself an arrow function parameter list, but it might
+  // form part of one.  Propagate speculative formal parameter error locations.
+  classifier->Accumulate(
+      arrow_formals_classifier,
+      ExpressionClassifier::StandardProductions |
+          ExpressionClassifier::FormalParametersProductions |
+          ExpressionClassifier::CoverInitializedNameProduction);
+
+  bool maybe_pattern =
+      (expression->IsObjectLiteral() || expression->IsArrayLiteral()) &&
+      !expression->is_parenthesized();
+
+  if (!Token::IsAssignmentOp(peek())) {
+    // Parsed conditional expression only (no assignment).
+    if (maybe_pattern_element) {
+      CheckDestructuringElement(expression, classifier, lhs_beg_pos,
+                                scanner()->location().end_pos);
+    }
+    return expression;
+  }
+
+  if (!(allow_harmony_destructuring_bind() ||
+        allow_harmony_default_parameters())) {
+    BindingPatternUnexpectedToken(classifier);
+  }
+
+  if (allow_harmony_destructuring_assignment() && maybe_pattern &&
+      peek() == Token::ASSIGN) {
+    classifier->ForgiveCoverInitializedNameError();
+    ValidateAssignmentPattern(classifier, CHECK_OK);
+    is_destructuring_assignment = true;
+  } else if (maybe_arrow_formals) {
+    expression = this->ClassifyAndRewriteReferenceExpression(
+        classifier, expression, lhs_beg_pos, scanner()->location().end_pos,
+        MessageTemplate::kInvalidLhsInAssignment);
+  } else {
+    if (maybe_pattern_element) {
+      CheckDestructuringElement(expression, classifier, lhs_beg_pos,
+                                scanner()->location().end_pos);
+    }
+    expression = this->CheckAndRewriteReferenceExpression(
+        expression, lhs_beg_pos, scanner()->location().end_pos,
+        MessageTemplate::kInvalidLhsInAssignment, CHECK_OK);
+  }
+
+  expression = this->MarkExpressionAsAssigned(expression);
+
+  Token::Value op = Next();  // Get assignment operator.
+  if (op != Token::ASSIGN) {
+    classifier->RecordBindingPatternError(scanner()->location(),
+                                          MessageTemplate::kUnexpectedToken,
+                                          Token::String(op));
+  }
+  int pos = position();
+
+  ExpressionClassifier rhs_classifier;
+
+  ExpressionT right =
+      this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK);
+  right = Traits::RewriteNonPattern(right, &rhs_classifier, CHECK_OK);
+  classifier->Accumulate(
+      rhs_classifier, ExpressionClassifier::ExpressionProductions |
+                          ExpressionClassifier::CoverInitializedNameProduction);
+
+  // TODO(1231235): We try to estimate the set of properties set by
+  // constructors. We define a new property whenever there is an
+  // assignment to a property of 'this'. We should probably only add
+  // properties if we haven't seen them before. Otherwise we'll
+  // probably overestimate the number of properties.
+  if (op == Token::ASSIGN && this->IsThisProperty(expression)) {
+    function_state_->AddProperty();
+  }
+
+  if (op != Token::ASSIGN && maybe_pattern_element) {
+    classifier->RecordAssignmentPatternError(
+        Scanner::Location(lhs_beg_pos, scanner()->location().end_pos),
+        MessageTemplate::kInvalidDestructuringTarget);
+  }
+
+  this->CheckAssigningFunctionLiteralToProperty(expression, right);
+
+  if (fni_ != NULL) {
+    // Check if the right hand side is a call to avoid inferring a
+    // name if we're dealing with "a = function(){...}();"-like
+    // expression.
+    if ((op == Token::INIT || op == Token::ASSIGN) &&
+        (!right->IsCall() && !right->IsCallNew())) {
+      fni_->Infer();
+    } else {
+      fni_->RemoveLastFunction();
+    }
+  }
+
+  if (op == Token::ASSIGN && allow_harmony_function_name()) {
+    Traits::SetFunctionNameFromIdentifierRef(right, expression);
+  }
+
+  ExpressionT result = factory()->NewAssignment(op, expression, right, pos);
+
+  if (is_destructuring_assignment) {
+    result = factory()->NewRewritableAssignmentExpression(result);
+    Traits::QueueDestructuringAssignmentForRewriting(result);
+  }
+
+  return result;
+}
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseYieldExpression(ExpressionClassifier* classifier,
+                                         bool* ok) {
+  // YieldExpression ::
+  //   'yield' ([no line terminator] '*'? AssignmentExpression)?
+  int pos = peek_position();
+  classifier->RecordPatternError(scanner()->peek_location(),
+                                 MessageTemplate::kInvalidDestructuringTarget);
+  FormalParameterInitializerUnexpectedToken(classifier);
+  Expect(Token::YIELD, CHECK_OK);
+  ExpressionT generator_object =
+      factory()->NewVariableProxy(function_state_->generator_object_variable());
+  ExpressionT expression = Traits::EmptyExpression();
+  Yield::Kind kind = Yield::kSuspend;
+  if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
+    if (Check(Token::MUL)) kind = Yield::kDelegating;
+    switch (peek()) {
+      case Token::EOS:
+      case Token::SEMICOLON:
+      case Token::RBRACE:
+      case Token::RBRACK:
+      case Token::RPAREN:
+      case Token::COLON:
+      case Token::COMMA:
+        // The above set of tokens is the complete set of tokens that can appear
+        // after an AssignmentExpression, and none of them can start an
+        // AssignmentExpression.  This allows us to avoid looking for an RHS for
+        // a Yield::kSuspend operation, given only one look-ahead token.
+        if (kind == Yield::kSuspend)
+          break;
+        DCHECK_EQ(Yield::kDelegating, kind);
+        // Delegating yields require an RHS; fall through.
+      default:
+        expression = ParseAssignmentExpression(false, classifier, CHECK_OK);
+        expression =
+            Traits::RewriteNonPattern(expression, classifier, CHECK_OK);
+        break;
+    }
+  }
+  if (kind == Yield::kDelegating) {
+    // var iterator = subject[Symbol.iterator]();
+    // Hackily disambiguate o from o.next and o [Symbol.iterator]().
+    // TODO(verwaest): Come up with a better solution.
+    expression = this->GetIterator(expression, factory(), pos + 1);
+  }
+  // Hackily disambiguate o from o.next and o [Symbol.iterator]().
+  // TODO(verwaest): Come up with a better solution.
+  typename Traits::Type::YieldExpression yield =
+      factory()->NewYield(generator_object, expression, kind, pos);
+  return yield;
+}
+
+
+// Precedence = 3
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseConditionalExpression(bool accept_IN,
+                                               ExpressionClassifier* classifier,
+                                               bool* ok) {
+  // ConditionalExpression ::
+  //   LogicalOrExpression
+  //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
+
+  int pos = peek_position();
+  // We start using the binary expression parser for prec >= 4 only!
+  ExpressionT expression =
+      this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK);
+  if (peek() != Token::CONDITIONAL) return expression;
+  expression = Traits::RewriteNonPattern(expression, classifier, CHECK_OK);
+  ArrowFormalParametersUnexpectedToken(classifier);
+  BindingPatternUnexpectedToken(classifier);
+  Consume(Token::CONDITIONAL);
+  // In parsing the first assignment expression in conditional
+  // expressions we always accept the 'in' keyword; see ECMA-262,
+  // section 11.12, page 58.
+  ExpressionT left = ParseAssignmentExpression(true, classifier, CHECK_OK);
+  left = Traits::RewriteNonPattern(left, classifier, CHECK_OK);
+  Expect(Token::COLON, CHECK_OK);
+  ExpressionT right =
+      ParseAssignmentExpression(accept_IN, classifier, CHECK_OK);
+  right = Traits::RewriteNonPattern(right, classifier, CHECK_OK);
+  return factory()->NewConditional(expression, left, right, pos);
+}
+
+
+// Precedence >= 4
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN,
+                                          ExpressionClassifier* classifier,
+                                          bool* ok) {
+  DCHECK(prec >= 4);
+  ExpressionT x = this->ParseUnaryExpression(classifier, CHECK_OK);
+  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
+    // prec1 >= 4
+    while (Precedence(peek(), accept_IN) == prec1) {
+      x = Traits::RewriteNonPattern(x, classifier, CHECK_OK);
+      BindingPatternUnexpectedToken(classifier);
+      ArrowFormalParametersUnexpectedToken(classifier);
+      Token::Value op = Next();
+      Scanner::Location op_location = scanner()->location();
+      int pos = position();
+      ExpressionT y =
+          ParseBinaryExpression(prec1 + 1, accept_IN, classifier, CHECK_OK);
+      y = Traits::RewriteNonPattern(y, classifier, CHECK_OK);
+
+      if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
+                                                       factory())) {
+        continue;
+      }
+
+      // For now we distinguish between comparisons and other binary
+      // operations.  (We could combine the two and get rid of this
+      // code and AST node eventually.)
+      if (Token::IsCompareOp(op)) {
+        // We have a comparison.
+        Token::Value cmp = op;
+        switch (op) {
+          case Token::NE: cmp = Token::EQ; break;
+          case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
+          default: break;
+        }
+        if (cmp == Token::EQ && is_strong(language_mode())) {
+          ReportMessageAt(op_location, MessageTemplate::kStrongEqual);
+          *ok = false;
+          return this->EmptyExpression();
+        }
+        x = factory()->NewCompareOperation(cmp, x, y, pos);
+        if (cmp != op) {
+          // The comparison was negated - add a NOT.
+          x = factory()->NewUnaryOperation(Token::NOT, x, pos);
+        }
+
+      } else {
+        // We have a "normal" binary operation.
+        x = factory()->NewBinaryOperation(op, x, y, pos);
+      }
+    }
+  }
+  return x;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
+                                         bool* ok) {
+  // UnaryExpression ::
+  //   PostfixExpression
+  //   'delete' UnaryExpression
+  //   'void' UnaryExpression
+  //   'typeof' UnaryExpression
+  //   '++' UnaryExpression
+  //   '--' UnaryExpression
+  //   '+' UnaryExpression
+  //   '-' UnaryExpression
+  //   '~' UnaryExpression
+  //   '!' UnaryExpression
+
+  Token::Value op = peek();
+  if (Token::IsUnaryOp(op)) {
+    BindingPatternUnexpectedToken(classifier);
+    ArrowFormalParametersUnexpectedToken(classifier);
+
+    op = Next();
+    int pos = position();
+    ExpressionT expression = ParseUnaryExpression(classifier, CHECK_OK);
+    expression = Traits::RewriteNonPattern(expression, classifier, CHECK_OK);
+
+    if (op == Token::DELETE && is_strict(language_mode())) {
+      if (is_strong(language_mode())) {
+        ReportMessage(MessageTemplate::kStrongDelete);
+        *ok = false;
+        return this->EmptyExpression();
+      } else if (this->IsIdentifier(expression)) {
+        // "delete identifier" is a syntax error in strict mode.
+        ReportMessage(MessageTemplate::kStrictDelete);
+        *ok = false;
+        return this->EmptyExpression();
+      }
+    }
+
+    // Allow Traits do rewrite the expression.
+    return this->BuildUnaryExpression(expression, op, pos, factory());
+  } else if (Token::IsCountOp(op)) {
+    BindingPatternUnexpectedToken(classifier);
+    ArrowFormalParametersUnexpectedToken(classifier);
+    op = Next();
+    int beg_pos = peek_position();
+    ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK);
+    expression = this->CheckAndRewriteReferenceExpression(
+        expression, beg_pos, scanner()->location().end_pos,
+        MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK);
+    this->MarkExpressionAsAssigned(expression);
+    expression = Traits::RewriteNonPattern(expression, classifier, CHECK_OK);
+
+    return factory()->NewCountOperation(op,
+                                        true /* prefix */,
+                                        expression,
+                                        position());
+
+  } else {
+    return this->ParsePostfixExpression(classifier, ok);
+  }
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier,
+                                           bool* ok) {
+  // PostfixExpression ::
+  //   LeftHandSideExpression ('++' | '--')?
+
+  int lhs_beg_pos = peek_position();
+  ExpressionT expression =
+      this->ParseLeftHandSideExpression(classifier, CHECK_OK);
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
+      Token::IsCountOp(peek())) {
+    BindingPatternUnexpectedToken(classifier);
+    ArrowFormalParametersUnexpectedToken(classifier);
+
+    expression = this->CheckAndRewriteReferenceExpression(
+        expression, lhs_beg_pos, scanner()->location().end_pos,
+        MessageTemplate::kInvalidLhsInPostfixOp, CHECK_OK);
+    expression = this->MarkExpressionAsAssigned(expression);
+    expression = Traits::RewriteNonPattern(expression, classifier, CHECK_OK);
+
+    Token::Value next = Next();
+    expression =
+        factory()->NewCountOperation(next,
+                                     false /* postfix */,
+                                     expression,
+                                     position());
+  }
+  return expression;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseLeftHandSideExpression(
+    ExpressionClassifier* classifier, bool* ok) {
+  // LeftHandSideExpression ::
+  //   (NewExpression | MemberExpression) ...
+
+  ExpressionT result =
+      this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK);
+
+  while (true) {
+    switch (peek()) {
+      case Token::LBRACK: {
+        BindingPatternUnexpectedToken(classifier);
+        ArrowFormalParametersUnexpectedToken(classifier);
+        Consume(Token::LBRACK);
+        int pos = position();
+        ExpressionT index = ParseExpression(true, classifier, CHECK_OK);
+        index = Traits::RewriteNonPattern(index, classifier, CHECK_OK);
+        result = factory()->NewProperty(result, index, pos);
+        Expect(Token::RBRACK, CHECK_OK);
+        break;
+      }
+
+      case Token::LPAREN: {
+        result = Traits::RewriteNonPattern(result, classifier, CHECK_OK);
+        BindingPatternUnexpectedToken(classifier);
+        ArrowFormalParametersUnexpectedToken(classifier);
+
+        if (is_strong(language_mode()) && this->IsIdentifier(result) &&
+            this->IsEval(this->AsIdentifier(result))) {
+          ReportMessage(MessageTemplate::kStrongDirectEval);
+          *ok = false;
+          return this->EmptyExpression();
+        }
+        int pos;
+        if (scanner()->current_token() == Token::IDENTIFIER ||
+            scanner()->current_token() == Token::SUPER) {
+          // For call of an identifier we want to report position of
+          // the identifier as position of the call in the stack trace.
+          pos = position();
+        } else {
+          // For other kinds of calls we record position of the parenthesis as
+          // position of the call. Note that this is extremely important for
+          // expressions of the form function(){...}() for which call position
+          // should not point to the closing brace otherwise it will intersect
+          // with positions recorded for function literal and confuse debugger.
+          pos = peek_position();
+          // Also the trailing parenthesis are a hint that the function will
+          // be called immediately. If we happen to have parsed a preceding
+          // function literal eagerly, we can also compile it eagerly.
+          if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
+            result->AsFunctionLiteral()->set_should_eager_compile();
+          }
+        }
+        Scanner::Location spread_pos;
+        typename Traits::Type::ExpressionList args =
+            ParseArguments(&spread_pos, classifier, CHECK_OK);
+
+        // Keep track of eval() calls since they disable all local variable
+        // optimizations.
+        // The calls that need special treatment are the
+        // direct eval calls. These calls are all of the form eval(...), with
+        // no explicit receiver.
+        // These calls are marked as potentially direct eval calls. Whether
+        // they are actually direct calls to eval is determined at run time.
+        this->CheckPossibleEvalCall(result, scope_);
+
+        bool is_super_call = result->IsSuperCallReference();
+        if (spread_pos.IsValid()) {
+          args = Traits::PrepareSpreadArguments(args);
+          result = Traits::SpreadCall(result, args, pos);
+        } else {
+          result = factory()->NewCall(result, args, pos);
+        }
+
+        // Explicit calls to the super constructor using super() perform an
+        // implicit binding assignment to the 'this' variable.
+        if (is_super_call) {
+          ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
+          result =
+              factory()->NewAssignment(Token::INIT, this_expr, result, pos);
+        }
+
+        if (fni_ != NULL) fni_->RemoveLastFunction();
+        break;
+      }
+
+      case Token::PERIOD: {
+        BindingPatternUnexpectedToken(classifier);
+        ArrowFormalParametersUnexpectedToken(classifier);
+        Consume(Token::PERIOD);
+        int pos = position();
+        IdentifierT name = ParseIdentifierName(CHECK_OK);
+        result = factory()->NewProperty(
+            result, factory()->NewStringLiteral(name, pos), pos);
+        if (fni_ != NULL) this->PushLiteralName(fni_, name);
+        break;
+      }
+
+      case Token::TEMPLATE_SPAN:
+      case Token::TEMPLATE_TAIL: {
+        BindingPatternUnexpectedToken(classifier);
+        ArrowFormalParametersUnexpectedToken(classifier);
+        result = ParseTemplateLiteral(result, position(), classifier, CHECK_OK);
+        break;
+      }
+
+      default:
+        return result;
+    }
+  }
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(
+    ExpressionClassifier* classifier, bool* ok) {
+  // NewExpression ::
+  //   ('new')+ MemberExpression
+  //
+  // NewTarget ::
+  //   'new' '.' 'target'
+
+  // The grammar for new expressions is pretty warped. We can have several 'new'
+  // keywords following each other, and then a MemberExpression. When we see '('
+  // after the MemberExpression, it's associated with the rightmost unassociated
+  // 'new' to create a NewExpression with arguments. However, a NewExpression
+  // can also occur without arguments.
+
+  // Examples of new expression:
+  // new foo.bar().baz means (new (foo.bar)()).baz
+  // new foo()() means (new foo())()
+  // new new foo()() means (new (new foo())())
+  // new new foo means new (new foo)
+  // new new foo() means new (new foo())
+  // new new foo().bar().baz means (new (new foo()).bar()).baz
+
+  if (peek() == Token::NEW) {
+    BindingPatternUnexpectedToken(classifier);
+    ArrowFormalParametersUnexpectedToken(classifier);
+    Consume(Token::NEW);
+    int new_pos = position();
+    ExpressionT result = this->EmptyExpression();
+    if (peek() == Token::SUPER) {
+      const bool is_new = true;
+      result = ParseSuperExpression(is_new, classifier, CHECK_OK);
+    } else if (peek() == Token::PERIOD) {
+      return ParseNewTargetExpression(CHECK_OK);
+    } else {
+      result = this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK);
+    }
+    result = Traits::RewriteNonPattern(result, classifier, CHECK_OK);
+    if (peek() == Token::LPAREN) {
+      // NewExpression with arguments.
+      Scanner::Location spread_pos;
+      typename Traits::Type::ExpressionList args =
+          this->ParseArguments(&spread_pos, classifier, CHECK_OK);
+
+      if (spread_pos.IsValid()) {
+        args = Traits::PrepareSpreadArguments(args);
+        result = Traits::SpreadCallNew(result, args, new_pos);
+      } else {
+        result = factory()->NewCallNew(result, args, new_pos);
+      }
+      // The expression can still continue with . or [ after the arguments.
+      result =
+          this->ParseMemberExpressionContinuation(result, classifier, CHECK_OK);
+      return result;
+    }
+    // NewExpression without arguments.
+    return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
+                                 new_pos);
+  }
+  // No 'new' or 'super' keyword.
+  return this->ParseMemberExpression(classifier, ok);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
+                                          bool* ok) {
+  // MemberExpression ::
+  //   (PrimaryExpression | FunctionLiteral | ClassLiteral)
+  //     ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
+
+  // The '[' Expression ']' and '.' Identifier parts are parsed by
+  // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
+  // caller.
+
+  // Parse the initial primary or function expression.
+  ExpressionT result = this->EmptyExpression();
+  if (peek() == Token::FUNCTION) {
+    BindingPatternUnexpectedToken(classifier);
+    ArrowFormalParametersUnexpectedToken(classifier);
+
+    Consume(Token::FUNCTION);
+    int function_token_position = position();
+    bool is_generator = Check(Token::MUL);
+    IdentifierT name = this->EmptyIdentifier();
+    bool is_strict_reserved_name = false;
+    Scanner::Location function_name_location = Scanner::Location::invalid();
+    FunctionLiteral::FunctionType function_type =
+        FunctionLiteral::kAnonymousExpression;
+    if (peek_any_identifier()) {
+      name = ParseIdentifierOrStrictReservedWord(
+          is_generator, &is_strict_reserved_name, CHECK_OK);
+      function_name_location = scanner()->location();
+      function_type = FunctionLiteral::kNamedExpression;
+    }
+    result = this->ParseFunctionLiteral(
+        name, function_name_location,
+        is_strict_reserved_name ? kFunctionNameIsStrictReserved
+                                : kFunctionNameValidityUnknown,
+        is_generator ? FunctionKind::kGeneratorFunction
+                     : FunctionKind::kNormalFunction,
+        function_token_position, function_type, FunctionLiteral::kNormalArity,
+        language_mode(), CHECK_OK);
+  } else if (peek() == Token::SUPER) {
+    const bool is_new = false;
+    result = ParseSuperExpression(is_new, classifier, CHECK_OK);
+  } else {
+    result = ParsePrimaryExpression(classifier, CHECK_OK);
+  }
+
+  result = ParseMemberExpressionContinuation(result, classifier, CHECK_OK);
+  return result;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseStrongInitializationExpression(
+    ExpressionClassifier* classifier, bool* ok) {
+  // InitializationExpression ::  (strong mode)
+  //  'this' '.' IdentifierName '=' AssignmentExpression
+  //  'this' '[' Expression ']' '=' AssignmentExpression
+
+  FuncNameInferrer::State fni_state(fni_);
+
+  Consume(Token::THIS);
+  int pos = position();
+  function_state_->set_this_location(scanner()->location());
+  ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
+
+  ExpressionT left = this->EmptyExpression();
+  switch (peek()) {
+    case Token::LBRACK: {
+      Consume(Token::LBRACK);
+      int pos = position();
+      ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK);
+      index = Traits::RewriteNonPattern(index, classifier, CHECK_OK);
+      left = factory()->NewProperty(this_expr, index, pos);
+      if (fni_ != NULL) {
+        this->PushPropertyName(fni_, index);
+      }
+      Expect(Token::RBRACK, CHECK_OK);
+      break;
+    }
+    case Token::PERIOD: {
+      Consume(Token::PERIOD);
+      int pos = position();
+      IdentifierT name = ParseIdentifierName(CHECK_OK);
+      left = factory()->NewProperty(
+          this_expr, factory()->NewStringLiteral(name, pos), pos);
+      if (fni_ != NULL) {
+        this->PushLiteralName(fni_, name);
+      }
+      break;
+    }
+    default:
+      ReportMessage(MessageTemplate::kStrongConstructorThis);
+      *ok = false;
+      return this->EmptyExpression();
+  }
+
+  if (peek() != Token::ASSIGN) {
+    ReportMessageAt(function_state_->this_location(),
+                    MessageTemplate::kStrongConstructorThis);
+    *ok = false;
+    return this->EmptyExpression();
+  }
+  Consume(Token::ASSIGN);
+  left = this->MarkExpressionAsAssigned(left);
+
+  ExpressionT right =
+      this->ParseAssignmentExpression(true, classifier, CHECK_OK);
+  right = Traits::RewriteNonPattern(right, classifier, CHECK_OK);
+  this->CheckAssigningFunctionLiteralToProperty(left, right);
+  function_state_->AddProperty();
+  if (fni_ != NULL) {
+    // Check if the right hand side is a call to avoid inferring a
+    // name if we're dealing with "this.a = function(){...}();"-like
+    // expression.
+    if (!right->IsCall() && !right->IsCallNew()) {
+      fni_->Infer();
+    } else {
+      fni_->RemoveLastFunction();
+    }
+  }
+
+  if (function_state_->return_location().IsValid()) {
+    ReportMessageAt(function_state_->return_location(),
+                    MessageTemplate::kStrongConstructorReturnMisplaced);
+    *ok = false;
+    return this->EmptyExpression();
+  }
+
+  return factory()->NewAssignment(Token::ASSIGN, left, right, pos);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseStrongSuperCallExpression(
+    ExpressionClassifier* classifier, bool* ok) {
+  // SuperCallExpression ::  (strong mode)
+  //  'super' '(' ExpressionList ')'
+  BindingPatternUnexpectedToken(classifier);
+
+  Consume(Token::SUPER);
+  int pos = position();
+  Scanner::Location super_loc = scanner()->location();
+  ExpressionT expr = this->SuperCallReference(scope_, factory(), pos);
+
+  if (peek() != Token::LPAREN) {
+    ReportMessage(MessageTemplate::kStrongConstructorSuper);
+    *ok = false;
+    return this->EmptyExpression();
+  }
+
+  Scanner::Location spread_pos;
+  typename Traits::Type::ExpressionList args =
+      ParseArguments(&spread_pos, classifier, CHECK_OK);
+
+  // TODO(rossberg): This doesn't work with arrow functions yet.
+  if (!IsSubclassConstructor(function_state_->kind())) {
+    ReportMessage(MessageTemplate::kUnexpectedSuper);
+    *ok = false;
+    return this->EmptyExpression();
+  } else if (function_state_->super_location().IsValid()) {
+    ReportMessageAt(scanner()->location(),
+                    MessageTemplate::kStrongSuperCallDuplicate);
+    *ok = false;
+    return this->EmptyExpression();
+  } else if (function_state_->this_location().IsValid()) {
+    ReportMessageAt(scanner()->location(),
+                    MessageTemplate::kStrongSuperCallMisplaced);
+    *ok = false;
+    return this->EmptyExpression();
+  } else if (function_state_->return_location().IsValid()) {
+    ReportMessageAt(function_state_->return_location(),
+                    MessageTemplate::kStrongConstructorReturnMisplaced);
+    *ok = false;
+    return this->EmptyExpression();
+  }
+
+  function_state_->set_super_location(super_loc);
+  if (spread_pos.IsValid()) {
+    args = Traits::PrepareSpreadArguments(args);
+    expr = Traits::SpreadCall(expr, args, pos);
+  } else {
+    expr = factory()->NewCall(expr, args, pos);
+  }
+
+  // Explicit calls to the super constructor using super() perform an implicit
+  // binding assignment to the 'this' variable.
+  ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
+  return factory()->NewAssignment(Token::INIT, this_expr, expr, pos);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseSuperExpression(bool is_new,
+                                         ExpressionClassifier* classifier,
+                                         bool* ok) {
+  Expect(Token::SUPER, CHECK_OK);
+  int pos = position();
+
+  Scope* scope = scope_->ReceiverScope();
+  FunctionKind kind = scope->function_kind();
+  if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
+      IsClassConstructor(kind)) {
+    if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
+      scope->RecordSuperPropertyUsage();
+      return this->SuperPropertyReference(scope_, factory(), pos);
+    }
+    // new super() is never allowed.
+    // super() is only allowed in derived constructor
+    if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) {
+      if (is_strong(language_mode())) {
+        // Super calls in strong mode are parsed separately.
+        ReportMessageAt(scanner()->location(),
+                        MessageTemplate::kStrongConstructorSuper);
+        *ok = false;
+        return this->EmptyExpression();
+      }
+      // TODO(rossberg): This might not be the correct FunctionState for the
+      // method here.
+      function_state_->set_super_location(scanner()->location());
+      return this->SuperCallReference(scope_, factory(), pos);
+    }
+  }
+
+  ReportMessageAt(scanner()->location(), MessageTemplate::kUnexpectedSuper);
+  *ok = false;
+  return this->EmptyExpression();
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseNewTargetExpression(bool* ok) {
+  int pos = position();
+  Consume(Token::PERIOD);
+  ExpectContextualKeyword(CStrVector("target"), CHECK_OK);
+
+  if (!scope_->ReceiverScope()->is_function_scope()) {
+    ReportMessageAt(scanner()->location(),
+                    MessageTemplate::kUnexpectedNewTarget);
+    *ok = false;
+    return this->EmptyExpression();
+  }
+
+  return this->NewTargetExpression(scope_, factory(), pos);
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseMemberExpressionContinuation(
+    ExpressionT expression, ExpressionClassifier* classifier, bool* ok) {
+  // Parses this part of MemberExpression:
+  // ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
+  while (true) {
+    switch (peek()) {
+      case Token::LBRACK: {
+        BindingPatternUnexpectedToken(classifier);
+        ArrowFormalParametersUnexpectedToken(classifier);
+
+        Consume(Token::LBRACK);
+        int pos = position();
+        ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK);
+        index = Traits::RewriteNonPattern(index, classifier, CHECK_OK);
+        expression = factory()->NewProperty(expression, index, pos);
+        if (fni_ != NULL) {
+          this->PushPropertyName(fni_, index);
+        }
+        Expect(Token::RBRACK, CHECK_OK);
+        break;
+      }
+      case Token::PERIOD: {
+        BindingPatternUnexpectedToken(classifier);
+        ArrowFormalParametersUnexpectedToken(classifier);
+
+        Consume(Token::PERIOD);
+        int pos = position();
+        IdentifierT name = ParseIdentifierName(CHECK_OK);
+        expression = factory()->NewProperty(
+            expression, factory()->NewStringLiteral(name, pos), pos);
+        if (fni_ != NULL) {
+          this->PushLiteralName(fni_, name);
+        }
+        break;
+      }
+      case Token::TEMPLATE_SPAN:
+      case Token::TEMPLATE_TAIL: {
+        BindingPatternUnexpectedToken(classifier);
+        ArrowFormalParametersUnexpectedToken(classifier);
+        int pos;
+        if (scanner()->current_token() == Token::IDENTIFIER) {
+          pos = position();
+        } else {
+          pos = peek_position();
+          if (expression->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
+            // If the tag function looks like an IIFE, set_parenthesized() to
+            // force eager compilation.
+            expression->AsFunctionLiteral()->set_should_eager_compile();
+          }
+        }
+        expression =
+            ParseTemplateLiteral(expression, pos, classifier, CHECK_OK);
+        break;
+      }
+      default:
+        return expression;
+    }
+  }
+  DCHECK(false);
+  return this->EmptyExpression();
+}
+
+
+template <class Traits>
+void ParserBase<Traits>::ParseFormalParameter(
+    FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) {
+  // FormalParameter[Yield,GeneratorParameter] :
+  //   BindingElement[?Yield, ?GeneratorParameter]
+  bool is_rest = parameters->has_rest;
+
+  Token::Value next = peek();
+  ExpressionT pattern = ParsePrimaryExpression(classifier, ok);
+  if (!*ok) return;
+
+  ValidateBindingPattern(classifier, ok);
+  if (!*ok) return;
+
+  if (!Traits::IsIdentifier(pattern)) {
+    if (!allow_harmony_destructuring_bind()) {
+      ReportUnexpectedToken(next);
+      *ok = false;
+      return;
+    }
+    parameters->is_simple = false;
+    ValidateFormalParameterInitializer(classifier, ok);
+    if (!*ok) return;
+    classifier->RecordNonSimpleParameter();
+  }
+
+  ExpressionT initializer = Traits::EmptyExpression();
+  if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) {
+    ExpressionClassifier init_classifier;
+    initializer = ParseAssignmentExpression(true, &init_classifier, ok);
+    if (!*ok) return;
+    initializer = Traits::RewriteNonPattern(initializer, &init_classifier, ok);
+    ValidateFormalParameterInitializer(&init_classifier, ok);
+    if (!*ok) return;
+    parameters->is_simple = false;
+    classifier->RecordNonSimpleParameter();
+  }
+
+  Traits::AddFormalParameter(parameters, pattern, initializer,
+                             scanner()->location().end_pos, is_rest);
+}
+
+
+template <class Traits>
+void ParserBase<Traits>::ParseFormalParameterList(
+    FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) {
+  // FormalParameters[Yield,GeneratorParameter] :
+  //   [empty]
+  //   FormalParameterList[?Yield, ?GeneratorParameter]
+  //
+  // FormalParameterList[Yield,GeneratorParameter] :
+  //   FunctionRestParameter[?Yield]
+  //   FormalsList[?Yield, ?GeneratorParameter]
+  //   FormalsList[?Yield, ?GeneratorParameter] , FunctionRestParameter[?Yield]
+  //
+  // FormalsList[Yield,GeneratorParameter] :
+  //   FormalParameter[?Yield, ?GeneratorParameter]
+  //   FormalsList[?Yield, ?GeneratorParameter] ,
+  //     FormalParameter[?Yield,?GeneratorParameter]
+
+  DCHECK_EQ(0, parameters->Arity());
+
+  if (peek() != Token::RPAREN) {
+    do {
+      if (parameters->Arity() > Code::kMaxArguments) {
+        ReportMessage(MessageTemplate::kTooManyParameters);
+        *ok = false;
+        return;
+      }
+      parameters->has_rest = Check(Token::ELLIPSIS);
+      ParseFormalParameter(parameters, classifier, ok);
+      if (!*ok) return;
+    } while (!parameters->has_rest && Check(Token::COMMA));
+
+    if (parameters->has_rest) {
+      parameters->is_simple = false;
+      classifier->RecordNonSimpleParameter();
+      if (peek() == Token::COMMA) {
+        ReportMessageAt(scanner()->peek_location(),
+                      MessageTemplate::kParamAfterRest);
+        *ok = false;
+        return;
+      }
+    }
+  }
+
+  for (int i = 0; i < parameters->Arity(); ++i) {
+    auto parameter = parameters->at(i);
+    Traits::DeclareFormalParameter(parameters->scope, parameter, classifier);
+  }
+}
+
+
+template <class Traits>
+void ParserBase<Traits>::CheckArityRestrictions(
+    int param_count, FunctionLiteral::ArityRestriction arity_restriction,
+    bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) {
+  switch (arity_restriction) {
+    case FunctionLiteral::kGetterArity:
+      if (param_count != 0) {
+        ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos),
+                        MessageTemplate::kBadGetterArity);
+        *ok = false;
+      }
+      break;
+    case FunctionLiteral::kSetterArity:
+      if (param_count != 1) {
+        ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos),
+                        MessageTemplate::kBadSetterArity);
+        *ok = false;
+      }
+      if (has_rest) {
+        ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos),
+                        MessageTemplate::kBadSetterRestParameter);
+        *ok = false;
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+
+template <class Traits>
+bool ParserBase<Traits>::IsNextLetKeyword() {
+  DCHECK(peek() == Token::LET);
+  if (!allow_let()) {
+    return false;
+  }
+  Token::Value next_next = PeekAhead();
+  switch (next_next) {
+    case Token::LBRACE:
+    case Token::LBRACK:
+    case Token::IDENTIFIER:
+    case Token::STATIC:
+    case Token::LET:  // Yes, you can do let let = ... in sloppy mode
+    case Token::YIELD:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseArrowFunctionLiteral(
+    bool accept_IN, const FormalParametersT& formal_parameters,
+    const ExpressionClassifier& formals_classifier, bool* ok) {
+  if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
+    // ASI inserts `;` after arrow parameters if a line terminator is found.
+    // `=> ...` is never a valid expression, so report as syntax error.
+    // If next token is not `=>`, it's a syntax error anyways.
+    ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW);
+    *ok = false;
+    return this->EmptyExpression();
+  }
+
+  typename Traits::Type::StatementList body;
+  int num_parameters = formal_parameters.scope->num_parameters();
+  int materialized_literal_count = -1;
+  int expected_property_count = -1;
+  Scanner::Location super_loc;
+
+  {
+    typename Traits::Type::Factory function_factory(ast_value_factory());
+    FunctionState function_state(&function_state_, &scope_,
+                                 formal_parameters.scope, kArrowFunction,
+                                 &function_factory);
+
+    function_state.SkipMaterializedLiterals(
+        formal_parameters.materialized_literals_count);
+
+    this->ReindexLiterals(formal_parameters);
+
+    Expect(Token::ARROW, CHECK_OK);
+
+    if (peek() == Token::LBRACE) {
+      // Multiple statement body
+      Consume(Token::LBRACE);
+      bool is_lazily_parsed =
+          (mode() == PARSE_LAZILY && scope_->AllowsLazyParsing());
+      if (is_lazily_parsed) {
+        body = this->NewStatementList(0, zone());
+        this->SkipLazyFunctionBody(&materialized_literal_count,
+                                   &expected_property_count, CHECK_OK);
+        if (formal_parameters.materialized_literals_count > 0) {
+          materialized_literal_count +=
+              formal_parameters.materialized_literals_count;
+        }
+      } else {
+        body = this->ParseEagerFunctionBody(
+            this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters,
+            kArrowFunction, FunctionLiteral::kAnonymousExpression, CHECK_OK);
+        materialized_literal_count =
+            function_state.materialized_literal_count();
+        expected_property_count = function_state.expected_property_count();
+      }
+    } else {
+      // Single-expression body
+      int pos = position();
+      parenthesized_function_ = false;
+      ExpressionClassifier classifier;
+      ExpressionT expression =
+          ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK);
+      expression = Traits::RewriteNonPattern(expression, &classifier, CHECK_OK);
+      body = this->NewStatementList(1, zone());
+      this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK);
+      body->Add(factory()->NewReturnStatement(expression, pos), zone());
+      materialized_literal_count = function_state.materialized_literal_count();
+      expected_property_count = function_state.expected_property_count();
+    }
+    super_loc = function_state.super_location();
+
+    formal_parameters.scope->set_end_position(scanner()->location().end_pos);
+
+    // Arrow function formal parameters are parsed as StrictFormalParameterList,
+    // which is not the same as "parameters of a strict function"; it only means
+    // that duplicates are not allowed.  Of course, the arrow function may
+    // itself be strict as well.
+    const bool allow_duplicate_parameters = false;
+    this->ValidateFormalParameters(&formals_classifier, language_mode(),
+                                   allow_duplicate_parameters, CHECK_OK);
+
+    // Validate strict mode.
+    if (is_strict(language_mode())) {
+      CheckStrictOctalLiteral(formal_parameters.scope->start_position(),
+                              scanner()->location().end_pos, CHECK_OK);
+    }
+    if (is_strict(language_mode()) || allow_harmony_sloppy()) {
+      this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
+    }
+
+    Traits::RewriteDestructuringAssignments();
+  }
+
+  FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
+      this->EmptyIdentifierString(), formal_parameters.scope, body,
+      materialized_literal_count, expected_property_count, num_parameters,
+      FunctionLiteral::kNoDuplicateParameters,
+      FunctionLiteral::kAnonymousExpression,
+      FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction,
+      formal_parameters.scope->start_position());
+
+  function_literal->set_function_token_position(
+      formal_parameters.scope->start_position());
+  if (super_loc.IsValid()) function_state_->set_super_location(super_loc);
+
+  if (fni_ != NULL) this->InferFunctionName(fni_, function_literal);
+
+  return function_literal;
+}
+
+
+template <typename Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start,
+                                         ExpressionClassifier* classifier,
+                                         bool* ok) {
+  // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
+  // text followed by a substitution expression), finalized by a single
+  // TEMPLATE_TAIL.
+  //
+  // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
+  // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
+  // NoSubstitutionTemplate.
+  //
+  // When parsing a TemplateLiteral, we must have scanned either an initial
+  // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
+  CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
+
+  // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
+  // In this case we may simply consume the token and build a template with a
+  // single TEMPLATE_SPAN and no expressions.
+  if (peek() == Token::TEMPLATE_TAIL) {
+    Consume(Token::TEMPLATE_TAIL);
+    int pos = position();
+    CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
+    typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
+    Traits::AddTemplateSpan(&ts, true);
+    return Traits::CloseTemplateLiteral(&ts, start, tag);
+  }
+
+  Consume(Token::TEMPLATE_SPAN);
+  int pos = position();
+  typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
+  Traits::AddTemplateSpan(&ts, false);
+  Token::Value next;
+
+  // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
+  // and repeat if the following token is a TEMPLATE_SPAN as well (in this
+  // case, representing a TemplateMiddle).
+
+  do {
+    CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
+    next = peek();
+    if (next == Token::EOS) {
+      ReportMessageAt(Scanner::Location(start, peek_position()),
+                      MessageTemplate::kUnterminatedTemplate);
+      *ok = false;
+      return Traits::EmptyExpression();
+    } else if (next == Token::ILLEGAL) {
+      Traits::ReportMessageAt(
+          Scanner::Location(position() + 1, peek_position()),
+          MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError);
+      *ok = false;
+      return Traits::EmptyExpression();
+    }
+
+    int expr_pos = peek_position();
+    ExpressionT expression = this->ParseExpression(true, classifier, CHECK_OK);
+    expression = Traits::RewriteNonPattern(expression, classifier, CHECK_OK);
+    Traits::AddTemplateExpression(&ts, expression);
+
+    if (peek() != Token::RBRACE) {
+      ReportMessageAt(Scanner::Location(expr_pos, peek_position()),
+                      MessageTemplate::kUnterminatedTemplateExpr);
+      *ok = false;
+      return Traits::EmptyExpression();
+    }
+
+    // If we didn't die parsing that expression, our next token should be a
+    // TEMPLATE_SPAN or TEMPLATE_TAIL.
+    next = scanner()->ScanTemplateContinuation();
+    Next();
+    pos = position();
+
+    if (next == Token::EOS) {
+      ReportMessageAt(Scanner::Location(start, pos),
+                      MessageTemplate::kUnterminatedTemplate);
+      *ok = false;
+      return Traits::EmptyExpression();
+    } else if (next == Token::ILLEGAL) {
+      Traits::ReportMessageAt(
+          Scanner::Location(position() + 1, peek_position()),
+          MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError);
+      *ok = false;
+      return Traits::EmptyExpression();
+    }
+
+    Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL);
+  } while (next == Token::TEMPLATE_SPAN);
+
+  DCHECK_EQ(next, Token::TEMPLATE_TAIL);
+  CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
+  // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
+  return Traits::CloseTemplateLiteral(&ts, start, tag);
+}
+
+
+template <typename Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::CheckAndRewriteReferenceExpression(
+    ExpressionT expression, int beg_pos, int end_pos,
+    MessageTemplate::Template message, bool* ok) {
+  return this->CheckAndRewriteReferenceExpression(expression, beg_pos, end_pos,
+                                                  message, kReferenceError, ok);
+}
+
+
+template <typename Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::CheckAndRewriteReferenceExpression(
+    ExpressionT expression, int beg_pos, int end_pos,
+    MessageTemplate::Template message, ParseErrorType type, bool* ok) {
+  ExpressionClassifier classifier;
+  ExpressionT result = ClassifyAndRewriteReferenceExpression(
+      &classifier, expression, beg_pos, end_pos, message, type);
+  ValidateExpression(&classifier, ok);
+  if (!*ok) return this->EmptyExpression();
+  return result;
+}
+
+
+template <typename Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ClassifyAndRewriteReferenceExpression(
+    ExpressionClassifier* classifier, ExpressionT expression, int beg_pos,
+    int end_pos, MessageTemplate::Template message, ParseErrorType type) {
+  Scanner::Location location(beg_pos, end_pos);
+  if (this->IsIdentifier(expression)) {
+    if (is_strict(language_mode()) &&
+        this->IsEvalOrArguments(this->AsIdentifier(expression))) {
+      classifier->RecordExpressionError(
+          location, MessageTemplate::kStrictEvalArguments, kSyntaxError);
+      return expression;
+    }
+    if (is_strong(language_mode()) &&
+        this->IsUndefined(this->AsIdentifier(expression))) {
+      classifier->RecordExpressionError(
+          location, MessageTemplate::kStrongUndefined, kSyntaxError);
+      return expression;
+    }
+  }
+  if (expression->IsValidReferenceExpression()) {
+    return expression;
+  } else if (expression->IsCall()) {
+    // If it is a call, make it a runtime error for legacy web compatibility.
+    // Rewrite `expr' to `expr[throw ReferenceError]'.
+    int pos = location.beg_pos;
+    ExpressionT error = this->NewThrowReferenceError(message, pos);
+    return factory()->NewProperty(expression, error, pos);
+  } else {
+    classifier->RecordExpressionError(location, message, type);
+    return expression;
+  }
+}
+
+
+template <typename Traits>
+bool ParserBase<Traits>::IsValidReferenceExpression(ExpressionT expression) {
+  return this->IsAssignableIdentifier(expression) || expression->IsProperty();
+}
+
+
+template <typename Traits>
+void ParserBase<Traits>::CheckDestructuringElement(
+    ExpressionT expression, ExpressionClassifier* classifier, int begin,
+    int end) {
+  static const MessageTemplate::Template message =
+      MessageTemplate::kInvalidDestructuringTarget;
+  const Scanner::Location location(begin, end);
+  if (expression->IsArrayLiteral() || expression->IsObjectLiteral() ||
+      expression->IsAssignment()) {
+    if (expression->is_parenthesized()) {
+      classifier->RecordPatternError(location, message);
+    }
+    return;
+  }
+
+  if (expression->IsProperty()) {
+    classifier->RecordBindingPatternError(location, message);
+  } else if (!this->IsAssignableIdentifier(expression)) {
+    classifier->RecordPatternError(location, message);
+  }
+}
+
+
+#undef CHECK_OK
+#undef CHECK_OK_CUSTOM
+
+
+template <typename Traits>
+void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
+    Token::Value property, PropertyKind type, bool is_static, bool is_generator,
+    bool* ok) {
+  DCHECK(!is_static);
+  DCHECK(!is_generator || type == kMethodProperty);
+
+  if (property == Token::SMI || property == Token::NUMBER) return;
+
+  if (type == kValueProperty && IsProto()) {
+    if (has_seen_proto_) {
+      this->parser()->ReportMessage(MessageTemplate::kDuplicateProto);
+      *ok = false;
+      return;
+    }
+    has_seen_proto_ = true;
+    return;
+  }
+}
+
+
+template <typename Traits>
+void ParserBase<Traits>::ClassLiteralChecker::CheckProperty(
+    Token::Value property, PropertyKind type, bool is_static, bool is_generator,
+    bool* ok) {
+  DCHECK(type == kMethodProperty || type == kAccessorProperty);
+
+  if (property == Token::SMI || property == Token::NUMBER) return;
+
+  if (is_static) {
+    if (IsPrototype()) {
+      this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
+      *ok = false;
+      return;
+    }
+  } else if (IsConstructor()) {
+    if (is_generator || type == kAccessorProperty) {
+      MessageTemplate::Template msg =
+          is_generator ? MessageTemplate::kConstructorIsGenerator
+                       : MessageTemplate::kConstructorIsAccessor;
+      this->parser()->ReportMessage(msg);
+      *ok = false;
+      return;
+    }
+    if (has_seen_constructor_) {
+      this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor);
+      *ok = false;
+      return;
+    }
+    has_seen_constructor_ = true;
+    return;
+  }
+}
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_PARSER_BASE_H
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
new file mode 100644
index 0000000..b1b8c13
--- /dev/null
+++ b/src/parsing/parser.cc
@@ -0,0 +1,5548 @@
+// 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.
+
+#include "src/parsing/parser.h"
+
+#include "src/api.h"
+#include "src/ast/ast.h"
+#include "src/ast/ast-expression-visitor.h"
+#include "src/ast/ast-literal-reindexer.h"
+#include "src/ast/scopeinfo.h"
+#include "src/bailout-reason.h"
+#include "src/base/platform/platform.h"
+#include "src/bootstrapper.h"
+#include "src/char-predicates-inl.h"
+#include "src/codegen.h"
+#include "src/compiler.h"
+#include "src/messages.h"
+#include "src/parsing/parameter-initializer-rewriter.h"
+#include "src/parsing/parser-base.h"
+#include "src/parsing/rewriter.h"
+#include "src/parsing/scanner-character-streams.h"
+#include "src/runtime/runtime.h"
+#include "src/string-stream.h"
+
+namespace v8 {
+namespace internal {
+
+ScriptData::ScriptData(const byte* data, int length)
+    : owns_data_(false), rejected_(false), data_(data), length_(length) {
+  if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) {
+    byte* copy = NewArray<byte>(length);
+    DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment));
+    CopyBytes(copy, data, length);
+    data_ = copy;
+    AcquireDataOwnership();
+  }
+}
+
+
+ParseInfo::ParseInfo(Zone* zone)
+    : zone_(zone),
+      flags_(0),
+      source_stream_(nullptr),
+      source_stream_encoding_(ScriptCompiler::StreamedSource::ONE_BYTE),
+      extension_(nullptr),
+      compile_options_(ScriptCompiler::kNoCompileOptions),
+      script_scope_(nullptr),
+      unicode_cache_(nullptr),
+      stack_limit_(0),
+      hash_seed_(0),
+      cached_data_(nullptr),
+      ast_value_factory_(nullptr),
+      literal_(nullptr),
+      scope_(nullptr) {}
+
+
+ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function)
+    : ParseInfo(zone, Handle<SharedFunctionInfo>(function->shared())) {
+  set_closure(function);
+  set_context(Handle<Context>(function->context()));
+}
+
+
+ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared)
+    : ParseInfo(zone) {
+  isolate_ = shared->GetIsolate();
+
+  set_lazy();
+  set_hash_seed(isolate_->heap()->HashSeed());
+  set_stack_limit(isolate_->stack_guard()->real_climit());
+  set_unicode_cache(isolate_->unicode_cache());
+  set_language_mode(shared->language_mode());
+  set_shared_info(shared);
+
+  Handle<Script> script(Script::cast(shared->script()));
+  set_script(script);
+  if (!script.is_null() && script->type() == Script::TYPE_NATIVE) {
+    set_native();
+  }
+}
+
+
+ParseInfo::ParseInfo(Zone* zone, Handle<Script> script) : ParseInfo(zone) {
+  isolate_ = script->GetIsolate();
+
+  set_hash_seed(isolate_->heap()->HashSeed());
+  set_stack_limit(isolate_->stack_guard()->real_climit());
+  set_unicode_cache(isolate_->unicode_cache());
+  set_script(script);
+
+  if (script->type() == Script::TYPE_NATIVE) {
+    set_native();
+  }
+}
+
+
+FunctionEntry ParseData::GetFunctionEntry(int start) {
+  // The current pre-data entry must be a FunctionEntry with the given
+  // start position.
+  if ((function_index_ + FunctionEntry::kSize <= Length()) &&
+      (static_cast<int>(Data()[function_index_]) == start)) {
+    int index = function_index_;
+    function_index_ += FunctionEntry::kSize;
+    Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
+    return FunctionEntry(subvector);
+  }
+  return FunctionEntry();
+}
+
+
+int ParseData::FunctionCount() {
+  int functions_size = FunctionsSize();
+  if (functions_size < 0) return 0;
+  if (functions_size % FunctionEntry::kSize != 0) return 0;
+  return functions_size / FunctionEntry::kSize;
+}
+
+
+bool ParseData::IsSane() {
+  if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false;
+  // Check that the header data is valid and doesn't specify
+  // point to positions outside the store.
+  int data_length = Length();
+  if (data_length < PreparseDataConstants::kHeaderSize) return false;
+  if (Magic() != PreparseDataConstants::kMagicNumber) return false;
+  if (Version() != PreparseDataConstants::kCurrentVersion) return false;
+  if (HasError()) return false;
+  // Check that the space allocated for function entries is sane.
+  int functions_size = FunctionsSize();
+  if (functions_size < 0) return false;
+  if (functions_size % FunctionEntry::kSize != 0) return false;
+  // Check that the total size has room for header and function entries.
+  int minimum_size =
+      PreparseDataConstants::kHeaderSize + functions_size;
+  if (data_length < minimum_size) return false;
+  return true;
+}
+
+
+void ParseData::Initialize() {
+  // Prepares state for use.
+  int data_length = Length();
+  if (data_length >= PreparseDataConstants::kHeaderSize) {
+    function_index_ = PreparseDataConstants::kHeaderSize;
+  }
+}
+
+
+bool ParseData::HasError() {
+  return Data()[PreparseDataConstants::kHasErrorOffset];
+}
+
+
+unsigned ParseData::Magic() {
+  return Data()[PreparseDataConstants::kMagicOffset];
+}
+
+
+unsigned ParseData::Version() {
+  return Data()[PreparseDataConstants::kVersionOffset];
+}
+
+
+int ParseData::FunctionsSize() {
+  return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
+}
+
+
+void Parser::SetCachedData(ParseInfo* info) {
+  if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
+    cached_parse_data_ = NULL;
+  } else {
+    DCHECK(info->cached_data() != NULL);
+    if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
+      cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
+    }
+  }
+}
+
+
+FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
+                                            int pos, int end_pos,
+                                            LanguageMode language_mode) {
+  int materialized_literal_count = -1;
+  int expected_property_count = -1;
+  int parameter_count = 0;
+  const AstRawString* name = ast_value_factory()->empty_string();
+
+
+  FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
+                                 : FunctionKind::kDefaultBaseConstructor;
+  Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind);
+  SetLanguageMode(function_scope,
+                  static_cast<LanguageMode>(language_mode | STRICT));
+  // Set start and end position to the same value
+  function_scope->set_start_position(pos);
+  function_scope->set_end_position(pos);
+  ZoneList<Statement*>* body = NULL;
+
+  {
+    AstNodeFactory function_factory(ast_value_factory());
+    FunctionState function_state(&function_state_, &scope_, function_scope,
+                                 kind, &function_factory);
+
+    body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
+    if (call_super) {
+      // $super_constructor = %_GetSuperConstructor(<this-function>)
+      // %reflect_construct($super_constructor, arguments, new.target)
+      ZoneList<Expression*>* args =
+          new (zone()) ZoneList<Expression*>(2, zone());
+      VariableProxy* this_function_proxy = scope_->NewUnresolved(
+          factory(), ast_value_factory()->this_function_string(),
+          Variable::NORMAL, pos);
+      ZoneList<Expression*>* tmp =
+          new (zone()) ZoneList<Expression*>(1, zone());
+      tmp->Add(this_function_proxy, zone());
+      Expression* super_constructor = factory()->NewCallRuntime(
+          Runtime::kInlineGetSuperConstructor, tmp, pos);
+      args->Add(super_constructor, zone());
+      VariableProxy* arguments_proxy = scope_->NewUnresolved(
+          factory(), ast_value_factory()->arguments_string(), Variable::NORMAL,
+          pos);
+      args->Add(arguments_proxy, zone());
+      VariableProxy* new_target_proxy = scope_->NewUnresolved(
+          factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
+          pos);
+      args->Add(new_target_proxy, zone());
+      CallRuntime* call = factory()->NewCallRuntime(
+          Context::REFLECT_CONSTRUCT_INDEX, args, pos);
+      body->Add(factory()->NewReturnStatement(call, pos), zone());
+    }
+
+    materialized_literal_count = function_state.materialized_literal_count();
+    expected_property_count = function_state.expected_property_count();
+  }
+
+  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
+      name, function_scope, body, materialized_literal_count,
+      expected_property_count, parameter_count,
+      FunctionLiteral::kNoDuplicateParameters,
+      FunctionLiteral::kAnonymousExpression,
+      FunctionLiteral::kShouldLazyCompile, kind, pos);
+
+  return function_literal;
+}
+
+
+// ----------------------------------------------------------------------------
+// Target is a support class to facilitate manipulation of the
+// Parser's target_stack_ (the stack of potential 'break' and
+// 'continue' statement targets). Upon construction, a new target is
+// added; it is removed upon destruction.
+
+class Target BASE_EMBEDDED {
+ public:
+  Target(Target** variable, BreakableStatement* statement)
+      : variable_(variable), statement_(statement), previous_(*variable) {
+    *variable = this;
+  }
+
+  ~Target() {
+    *variable_ = previous_;
+  }
+
+  Target* previous() { return previous_; }
+  BreakableStatement* statement() { return statement_; }
+
+ private:
+  Target** variable_;
+  BreakableStatement* statement_;
+  Target* previous_;
+};
+
+
+class TargetScope BASE_EMBEDDED {
+ public:
+  explicit TargetScope(Target** variable)
+      : variable_(variable), previous_(*variable) {
+    *variable = NULL;
+  }
+
+  ~TargetScope() {
+    *variable_ = previous_;
+  }
+
+ private:
+  Target** variable_;
+  Target* previous_;
+};
+
+
+// ----------------------------------------------------------------------------
+// The CHECK_OK macro is a convenient macro to enforce error
+// handling for functions that may fail (by returning !*ok).
+//
+// CAUTION: This macro appends extra statements after a call,
+// thus it must never be used where only a single statement
+// is correct (e.g. an if statement branch w/o braces)!
+
+#define CHECK_OK  ok);   \
+  if (!*ok) return NULL; \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+#define CHECK_FAILED  /**/);   \
+  if (failed_) return NULL; \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+// ----------------------------------------------------------------------------
+// Implementation of Parser
+
+bool ParserTraits::IsEval(const AstRawString* identifier) const {
+  return identifier == parser_->ast_value_factory()->eval_string();
+}
+
+
+bool ParserTraits::IsArguments(const AstRawString* identifier) const {
+  return identifier == parser_->ast_value_factory()->arguments_string();
+}
+
+
+bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
+  return IsEval(identifier) || IsArguments(identifier);
+}
+
+bool ParserTraits::IsUndefined(const AstRawString* identifier) const {
+  return identifier == parser_->ast_value_factory()->undefined_string();
+}
+
+bool ParserTraits::IsPrototype(const AstRawString* identifier) const {
+  return identifier == parser_->ast_value_factory()->prototype_string();
+}
+
+
+bool ParserTraits::IsConstructor(const AstRawString* identifier) const {
+  return identifier == parser_->ast_value_factory()->constructor_string();
+}
+
+
+bool ParserTraits::IsThisProperty(Expression* expression) {
+  DCHECK(expression != NULL);
+  Property* property = expression->AsProperty();
+  return property != NULL && property->obj()->IsVariableProxy() &&
+         property->obj()->AsVariableProxy()->is_this();
+}
+
+
+bool ParserTraits::IsIdentifier(Expression* expression) {
+  VariableProxy* operand = expression->AsVariableProxy();
+  return operand != NULL && !operand->is_this();
+}
+
+
+void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
+                                    Expression* expression) {
+  if (expression->IsPropertyName()) {
+    fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
+  } else {
+    fni->PushLiteralName(
+        parser_->ast_value_factory()->anonymous_function_string());
+  }
+}
+
+
+void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
+                                                           Expression* right) {
+  DCHECK(left != NULL);
+  if (left->IsProperty() && right->IsFunctionLiteral()) {
+    right->AsFunctionLiteral()->set_pretenure();
+  }
+}
+
+
+Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) {
+  VariableProxy* proxy =
+      expression != NULL ? expression->AsVariableProxy() : NULL;
+  if (proxy != NULL) proxy->set_is_assigned();
+  return expression;
+}
+
+
+bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
+    Expression** x, Expression* y, Token::Value op, int pos,
+    AstNodeFactory* factory) {
+  if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
+      y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
+    double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
+    double y_val = y->AsLiteral()->raw_value()->AsNumber();
+    bool x_has_dot = (*x)->AsLiteral()->raw_value()->ContainsDot();
+    bool y_has_dot = y->AsLiteral()->raw_value()->ContainsDot();
+    bool has_dot = x_has_dot || y_has_dot;
+    switch (op) {
+      case Token::ADD:
+        *x = factory->NewNumberLiteral(x_val + y_val, pos, has_dot);
+        return true;
+      case Token::SUB:
+        *x = factory->NewNumberLiteral(x_val - y_val, pos, has_dot);
+        return true;
+      case Token::MUL:
+        *x = factory->NewNumberLiteral(x_val * y_val, pos, has_dot);
+        return true;
+      case Token::DIV:
+        *x = factory->NewNumberLiteral(x_val / y_val, pos, has_dot);
+        return true;
+      case Token::BIT_OR: {
+        int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
+        *x = factory->NewNumberLiteral(value, pos, has_dot);
+        return true;
+      }
+      case Token::BIT_AND: {
+        int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
+        *x = factory->NewNumberLiteral(value, pos, has_dot);
+        return true;
+      }
+      case Token::BIT_XOR: {
+        int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
+        *x = factory->NewNumberLiteral(value, pos, has_dot);
+        return true;
+      }
+      case Token::SHL: {
+        int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
+        *x = factory->NewNumberLiteral(value, pos, has_dot);
+        return true;
+      }
+      case Token::SHR: {
+        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
+        uint32_t value = DoubleToUint32(x_val) >> shift;
+        *x = factory->NewNumberLiteral(value, pos, has_dot);
+        return true;
+      }
+      case Token::SAR: {
+        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
+        int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
+        *x = factory->NewNumberLiteral(value, pos, has_dot);
+        return true;
+      }
+      default:
+        break;
+    }
+  }
+  return false;
+}
+
+
+Expression* ParserTraits::BuildUnaryExpression(Expression* expression,
+                                               Token::Value op, int pos,
+                                               AstNodeFactory* factory) {
+  DCHECK(expression != NULL);
+  if (expression->IsLiteral()) {
+    const AstValue* literal = expression->AsLiteral()->raw_value();
+    if (op == Token::NOT) {
+      // Convert the literal to a boolean condition and negate it.
+      bool condition = literal->BooleanValue();
+      return factory->NewBooleanLiteral(!condition, pos);
+    } else if (literal->IsNumber()) {
+      // Compute some expressions involving only number literals.
+      double value = literal->AsNumber();
+      bool has_dot = literal->ContainsDot();
+      switch (op) {
+        case Token::ADD:
+          return expression;
+        case Token::SUB:
+          return factory->NewNumberLiteral(-value, pos, has_dot);
+        case Token::BIT_NOT:
+          return factory->NewNumberLiteral(~DoubleToInt32(value), pos, has_dot);
+        default:
+          break;
+      }
+    }
+  }
+  // Desugar '+foo' => 'foo*1'
+  if (op == Token::ADD) {
+    return factory->NewBinaryOperation(
+        Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos);
+  }
+  // The same idea for '-foo' => 'foo*(-1)'.
+  if (op == Token::SUB) {
+    return factory->NewBinaryOperation(
+        Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
+  }
+  // ...and one more time for '~foo' => 'foo^(~0)'.
+  if (op == Token::BIT_NOT) {
+    return factory->NewBinaryOperation(
+        Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
+  }
+  return factory->NewUnaryOperation(op, expression, pos);
+}
+
+
+Expression* ParserTraits::NewThrowReferenceError(
+    MessageTemplate::Template message, int pos) {
+  return NewThrowError(Runtime::kNewReferenceError, message,
+                       parser_->ast_value_factory()->empty_string(), pos);
+}
+
+
+Expression* ParserTraits::NewThrowSyntaxError(MessageTemplate::Template message,
+                                              const AstRawString* arg,
+                                              int pos) {
+  return NewThrowError(Runtime::kNewSyntaxError, message, arg, pos);
+}
+
+
+Expression* ParserTraits::NewThrowTypeError(MessageTemplate::Template message,
+                                            const AstRawString* arg, int pos) {
+  return NewThrowError(Runtime::kNewTypeError, message, arg, pos);
+}
+
+
+Expression* ParserTraits::NewThrowError(Runtime::FunctionId id,
+                                        MessageTemplate::Template message,
+                                        const AstRawString* arg, int pos) {
+  Zone* zone = parser_->zone();
+  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
+  args->Add(parser_->factory()->NewSmiLiteral(message, pos), zone);
+  args->Add(parser_->factory()->NewStringLiteral(arg, pos), zone);
+  CallRuntime* call_constructor =
+      parser_->factory()->NewCallRuntime(id, args, pos);
+  return parser_->factory()->NewThrow(call_constructor, pos);
+}
+
+
+void ParserTraits::ReportMessageAt(Scanner::Location source_location,
+                                   MessageTemplate::Template message,
+                                   const char* arg, ParseErrorType error_type) {
+  if (parser_->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;
+  }
+  parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
+                                                  source_location.end_pos,
+                                                  message, arg, error_type);
+}
+
+
+void ParserTraits::ReportMessage(MessageTemplate::Template message,
+                                 const char* arg, ParseErrorType error_type) {
+  Scanner::Location source_location = parser_->scanner()->location();
+  ReportMessageAt(source_location, message, arg, error_type);
+}
+
+
+void ParserTraits::ReportMessage(MessageTemplate::Template message,
+                                 const AstRawString* arg,
+                                 ParseErrorType error_type) {
+  Scanner::Location source_location = parser_->scanner()->location();
+  ReportMessageAt(source_location, message, arg, error_type);
+}
+
+
+void ParserTraits::ReportMessageAt(Scanner::Location source_location,
+                                   MessageTemplate::Template message,
+                                   const AstRawString* arg,
+                                   ParseErrorType error_type) {
+  if (parser_->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;
+  }
+  parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
+                                                  source_location.end_pos,
+                                                  message, arg, error_type);
+}
+
+
+const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
+  const AstRawString* result =
+      parser_->scanner()->CurrentSymbol(parser_->ast_value_factory());
+  DCHECK(result != NULL);
+  return result;
+}
+
+
+const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) {
+  double double_value = parser_->scanner()->DoubleValue();
+  char array[100];
+  const char* string =
+      DoubleToCString(double_value, Vector<char>(array, arraysize(array)));
+  return parser_->ast_value_factory()->GetOneByteString(string);
+}
+
+
+const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
+  return parser_->scanner()->NextSymbol(parser_->ast_value_factory());
+}
+
+
+Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
+                                         int pos) {
+  return scope->NewUnresolved(factory,
+                              parser_->ast_value_factory()->this_string(),
+                              Variable::THIS, pos, pos + 4);
+}
+
+
+Expression* ParserTraits::SuperPropertyReference(Scope* scope,
+                                                 AstNodeFactory* factory,
+                                                 int pos) {
+  // this_function[home_object_symbol]
+  VariableProxy* this_function_proxy = scope->NewUnresolved(
+      factory, parser_->ast_value_factory()->this_function_string(),
+      Variable::NORMAL, pos);
+  Expression* home_object_symbol_literal =
+      factory->NewSymbolLiteral("home_object_symbol", RelocInfo::kNoPosition);
+  Expression* home_object = factory->NewProperty(
+      this_function_proxy, home_object_symbol_literal, pos);
+  return factory->NewSuperPropertyReference(
+      ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object, pos);
+}
+
+
+Expression* ParserTraits::SuperCallReference(Scope* scope,
+                                             AstNodeFactory* factory, int pos) {
+  VariableProxy* new_target_proxy = scope->NewUnresolved(
+      factory, parser_->ast_value_factory()->new_target_string(),
+      Variable::NORMAL, pos);
+  VariableProxy* this_function_proxy = scope->NewUnresolved(
+      factory, parser_->ast_value_factory()->this_function_string(),
+      Variable::NORMAL, pos);
+  return factory->NewSuperCallReference(
+      ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
+      this_function_proxy, pos);
+}
+
+
+Expression* ParserTraits::NewTargetExpression(Scope* scope,
+                                              AstNodeFactory* factory,
+                                              int pos) {
+  static const int kNewTargetStringLength = 10;
+  auto proxy = scope->NewUnresolved(
+      factory, parser_->ast_value_factory()->new_target_string(),
+      Variable::NORMAL, pos, pos + kNewTargetStringLength);
+  proxy->set_is_new_target();
+  return proxy;
+}
+
+
+Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope,
+                                             int pos, int end_pos,
+                                             LanguageMode mode) {
+  return parser_->DefaultConstructor(call_super, scope, pos, end_pos, mode);
+}
+
+
+Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos,
+                                             Scanner* scanner,
+                                             AstNodeFactory* factory) {
+  switch (token) {
+    case Token::NULL_LITERAL:
+      return factory->NewNullLiteral(pos);
+    case Token::TRUE_LITERAL:
+      return factory->NewBooleanLiteral(true, pos);
+    case Token::FALSE_LITERAL:
+      return factory->NewBooleanLiteral(false, pos);
+    case Token::SMI: {
+      int value = scanner->smi_value();
+      return factory->NewSmiLiteral(value, pos);
+    }
+    case Token::NUMBER: {
+      bool has_dot = scanner->ContainsDot();
+      double value = scanner->DoubleValue();
+      return factory->NewNumberLiteral(value, pos, has_dot);
+    }
+    default:
+      DCHECK(false);
+  }
+  return NULL;
+}
+
+
+Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
+                                                   int start_position,
+                                                   int end_position,
+                                                   Scope* scope,
+                                                   AstNodeFactory* factory) {
+  if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
+  return scope->NewUnresolved(factory, name, Variable::NORMAL, start_position,
+                              end_position);
+}
+
+
+Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner,
+                                               AstNodeFactory* factory) {
+  const AstRawString* symbol = GetSymbol(scanner);
+  if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
+  return factory->NewStringLiteral(symbol, pos);
+}
+
+
+Expression* ParserTraits::GetIterator(Expression* iterable,
+                                      AstNodeFactory* factory, int pos) {
+  Expression* iterator_symbol_literal =
+      factory->NewSymbolLiteral("iterator_symbol", RelocInfo::kNoPosition);
+  Expression* prop =
+      factory->NewProperty(iterable, iterator_symbol_literal, pos);
+  Zone* zone = parser_->zone();
+  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
+  return factory->NewCall(prop, args, pos);
+}
+
+
+Literal* ParserTraits::GetLiteralTheHole(int position,
+                                         AstNodeFactory* factory) {
+  return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
+}
+
+
+Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
+  return parser_->ParseV8Intrinsic(ok);
+}
+
+
+FunctionLiteral* ParserTraits::ParseFunctionLiteral(
+    const AstRawString* name, Scanner::Location function_name_location,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
+    int function_token_position, FunctionLiteral::FunctionType type,
+    FunctionLiteral::ArityRestriction arity_restriction,
+    LanguageMode language_mode, bool* ok) {
+  return parser_->ParseFunctionLiteral(
+      name, function_name_location, function_name_validity, kind,
+      function_token_position, type, arity_restriction, language_mode, ok);
+}
+
+
+ClassLiteral* ParserTraits::ParseClassLiteral(
+    const AstRawString* name, Scanner::Location class_name_location,
+    bool name_is_strict_reserved, int pos, bool* ok) {
+  return parser_->ParseClassLiteral(name, class_name_location,
+                                    name_is_strict_reserved, pos, ok);
+}
+
+
+Parser::Parser(ParseInfo* info)
+    : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
+                               info->extension(), info->ast_value_factory(),
+                               NULL, this),
+      scanner_(info->unicode_cache()),
+      reusable_preparser_(NULL),
+      original_scope_(NULL),
+      target_stack_(NULL),
+      compile_options_(info->compile_options()),
+      cached_parse_data_(NULL),
+      total_preparse_skipped_(0),
+      pre_parse_timer_(NULL),
+      parsing_on_main_thread_(true) {
+  // Even though we were passed ParseInfo, we should not store it in
+  // Parser - this makes sure that Isolate is not accidentally accessed via
+  // ParseInfo during background parsing.
+  DCHECK(!info->script().is_null() || info->source_stream() != NULL);
+  set_allow_lazy(info->allow_lazy_parsing());
+  set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
+  set_allow_harmony_sloppy(FLAG_harmony_sloppy);
+  set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
+  set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
+  set_allow_harmony_default_parameters(FLAG_harmony_default_parameters);
+  set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind);
+  set_allow_harmony_destructuring_assignment(
+      FLAG_harmony_destructuring_assignment);
+  set_allow_strong_mode(FLAG_strong_mode);
+  set_allow_legacy_const(FLAG_legacy_const);
+  set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
+  set_allow_harmony_function_name(FLAG_harmony_function_name);
+  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
+       ++feature) {
+    use_counts_[feature] = 0;
+  }
+  if (info->ast_value_factory() == NULL) {
+    // info takes ownership of AstValueFactory.
+    info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
+    info->set_ast_value_factory_owned();
+    ast_value_factory_ = info->ast_value_factory();
+  }
+}
+
+
+FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
+  // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
+  // see comment for HistogramTimerScope class.
+
+  // It's OK to use the Isolate & counters here, since this function is only
+  // called in the main thread.
+  DCHECK(parsing_on_main_thread_);
+
+  HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
+  Handle<String> source(String::cast(info->script()->source()));
+  isolate->counters()->total_parse_size()->Increment(source->length());
+  base::ElapsedTimer timer;
+  if (FLAG_trace_parse) {
+    timer.Start();
+  }
+  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
+
+  // Initialize parser state.
+  CompleteParserRecorder recorder;
+
+  if (produce_cached_parse_data()) {
+    log_ = &recorder;
+  } else if (consume_cached_parse_data()) {
+    cached_parse_data_->Initialize();
+  }
+
+  source = String::Flatten(source);
+  FunctionLiteral* result;
+
+  if (source->IsExternalTwoByteString()) {
+    // Notice that the stream is destroyed at the end of the branch block.
+    // The last line of the blocks can't be moved outside, even though they're
+    // identical calls.
+    ExternalTwoByteStringUtf16CharacterStream stream(
+        Handle<ExternalTwoByteString>::cast(source), 0, source->length());
+    scanner_.Initialize(&stream);
+    result = DoParseProgram(info);
+  } else {
+    GenericStringUtf16CharacterStream stream(source, 0, source->length());
+    scanner_.Initialize(&stream);
+    result = DoParseProgram(info);
+  }
+  if (result != NULL) {
+    DCHECK_EQ(scanner_.peek_location().beg_pos, source->length());
+  }
+  HandleSourceURLComments(isolate, info->script());
+
+  if (FLAG_trace_parse && result != NULL) {
+    double ms = timer.Elapsed().InMillisecondsF();
+    if (info->is_eval()) {
+      PrintF("[parsing eval");
+    } else if (info->script()->name()->IsString()) {
+      String* name = String::cast(info->script()->name());
+      base::SmartArrayPointer<char> name_chars = name->ToCString();
+      PrintF("[parsing script: %s", name_chars.get());
+    } else {
+      PrintF("[parsing script");
+    }
+    PrintF(" - took %0.3f ms]\n", ms);
+  }
+  if (produce_cached_parse_data()) {
+    if (result != NULL) *info->cached_data() = recorder.GetScriptData();
+    log_ = NULL;
+  }
+  return result;
+}
+
+
+FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
+  // Note that this function can be called from the main thread or from a
+  // background thread. We should not access anything Isolate / heap dependent
+  // via ParseInfo, and also not pass it forward.
+  DCHECK(scope_ == NULL);
+  DCHECK(target_stack_ == NULL);
+
+  Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY;
+  if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY;
+
+  FunctionLiteral* result = NULL;
+  {
+    // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
+    // context, which will have the "this" binding for script scopes.
+    Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
+    info->set_script_scope(scope);
+    if (!info->context().is_null() && !info->context()->IsNativeContext()) {
+      scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
+                                           *info->context(), scope);
+      // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
+      // means the Parser cannot operate independent of the V8 heap. Tell the
+      // string table to internalize strings and values right after they're
+      // created. This kind of parsing can only be done in the main thread.
+      DCHECK(parsing_on_main_thread_);
+      ast_value_factory()->Internalize(info->isolate());
+    }
+    original_scope_ = scope;
+    if (info->is_eval()) {
+      if (!scope->is_script_scope() || is_strict(info->language_mode())) {
+        parsing_mode = PARSE_EAGERLY;
+      }
+      scope = NewScope(scope, EVAL_SCOPE);
+    } else if (info->is_module()) {
+      scope = NewScope(scope, MODULE_SCOPE);
+    }
+
+    scope->set_start_position(0);
+
+    // Enter 'scope' with the given parsing mode.
+    ParsingModeScope parsing_mode_scope(this, parsing_mode);
+    AstNodeFactory function_factory(ast_value_factory());
+    FunctionState function_state(&function_state_, &scope_, scope,
+                                 kNormalFunction, &function_factory);
+
+    // Don't count the mode in the use counters--give the program a chance
+    // to enable script/module-wide strict/strong mode below.
+    scope_->SetLanguageMode(info->language_mode());
+    ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
+    bool ok = true;
+    int beg_pos = scanner()->location().beg_pos;
+    if (info->is_module()) {
+      ParseModuleItemList(body, &ok);
+    } else {
+      ParseStatementList(body, Token::EOS, &ok);
+    }
+
+    // The parser will peek but not consume EOS.  Our scope logically goes all
+    // the way to the EOS, though.
+    scope->set_end_position(scanner()->peek_location().beg_pos);
+
+    if (ok && is_strict(language_mode())) {
+      CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
+    }
+    if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) {
+      // TODO(littledan): Function bindings on the global object that modify
+      // pre-existing bindings should be made writable, enumerable and
+      // nonconfigurable if possible, whereas this code will leave attributes
+      // unchanged if the property already exists.
+      InsertSloppyBlockFunctionVarBindings(scope, &ok);
+    }
+    if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() ||
+               allow_harmony_destructuring_bind())) {
+      CheckConflictingVarDeclarations(scope_, &ok);
+    }
+
+    if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
+      if (body->length() != 1 ||
+          !body->at(0)->IsExpressionStatement() ||
+          !body->at(0)->AsExpressionStatement()->
+              expression()->IsFunctionLiteral()) {
+        ReportMessage(MessageTemplate::kSingleFunctionLiteral);
+        ok = false;
+      }
+    }
+
+    if (ok) {
+      ParserTraits::RewriteDestructuringAssignments();
+      result = factory()->NewFunctionLiteral(
+          ast_value_factory()->empty_string(), scope_, body,
+          function_state.materialized_literal_count(),
+          function_state.expected_property_count(), 0,
+          FunctionLiteral::kNoDuplicateParameters,
+          FunctionLiteral::kGlobalOrEval, FunctionLiteral::kShouldLazyCompile,
+          FunctionKind::kNormalFunction, 0);
+    }
+  }
+
+  // Make sure the target stack is empty.
+  DCHECK(target_stack_ == NULL);
+
+  return result;
+}
+
+
+FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
+  // It's OK to use the Isolate & counters here, since this function is only
+  // called in the main thread.
+  DCHECK(parsing_on_main_thread_);
+  HistogramTimerScope timer_scope(isolate->counters()->parse_lazy());
+  Handle<String> source(String::cast(info->script()->source()));
+  isolate->counters()->total_parse_size()->Increment(source->length());
+  base::ElapsedTimer timer;
+  if (FLAG_trace_parse) {
+    timer.Start();
+  }
+  Handle<SharedFunctionInfo> shared_info = info->shared_info();
+
+  // Initialize parser state.
+  source = String::Flatten(source);
+  FunctionLiteral* result;
+  if (source->IsExternalTwoByteString()) {
+    ExternalTwoByteStringUtf16CharacterStream stream(
+        Handle<ExternalTwoByteString>::cast(source),
+        shared_info->start_position(),
+        shared_info->end_position());
+    result = ParseLazy(isolate, info, &stream);
+  } else {
+    GenericStringUtf16CharacterStream stream(source,
+                                             shared_info->start_position(),
+                                             shared_info->end_position());
+    result = ParseLazy(isolate, info, &stream);
+  }
+
+  if (FLAG_trace_parse && result != NULL) {
+    double ms = timer.Elapsed().InMillisecondsF();
+    base::SmartArrayPointer<char> name_chars =
+        result->debug_name()->ToCString();
+    PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
+  }
+  return result;
+}
+
+
+FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
+                                   Utf16CharacterStream* source) {
+  Handle<SharedFunctionInfo> shared_info = info->shared_info();
+  scanner_.Initialize(source);
+  DCHECK(scope_ == NULL);
+  DCHECK(target_stack_ == NULL);
+
+  Handle<String> name(String::cast(shared_info->name()));
+  DCHECK(ast_value_factory());
+  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
+  const AstRawString* raw_name = ast_value_factory()->GetString(name);
+  fni_->PushEnclosingName(raw_name);
+
+  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
+
+  // Place holder for the result.
+  FunctionLiteral* result = NULL;
+
+  {
+    // Parse the function literal.
+    Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
+    info->set_script_scope(scope);
+    if (!info->closure().is_null()) {
+      // Ok to use Isolate here, since lazy function parsing is only done in the
+      // main thread.
+      DCHECK(parsing_on_main_thread_);
+      scope = Scope::DeserializeScopeChain(isolate, zone(),
+                                           info->closure()->context(), scope);
+    }
+    original_scope_ = scope;
+    AstNodeFactory function_factory(ast_value_factory());
+    FunctionState function_state(&function_state_, &scope_, scope,
+                                 shared_info->kind(), &function_factory);
+    DCHECK(is_sloppy(scope->language_mode()) ||
+           is_strict(info->language_mode()));
+    DCHECK(info->language_mode() == shared_info->language_mode());
+    FunctionLiteral::FunctionType function_type =
+        shared_info->is_expression()
+            ? (shared_info->is_anonymous()
+                   ? FunctionLiteral::kAnonymousExpression
+                   : FunctionLiteral::kNamedExpression)
+            : FunctionLiteral::kDeclaration;
+    bool ok = true;
+
+    if (shared_info->is_arrow()) {
+      // TODO(adamk): We should construct this scope from the ScopeInfo.
+      Scope* scope =
+          NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
+
+      // These two bits only need to be explicitly set because we're
+      // not passing the ScopeInfo to the Scope constructor.
+      // TODO(adamk): Remove these calls once the above NewScope call
+      // passes the ScopeInfo.
+      if (shared_info->scope_info()->CallsEval()) {
+        scope->RecordEvalCall();
+      }
+      SetLanguageMode(scope, shared_info->language_mode());
+
+      scope->set_start_position(shared_info->start_position());
+      ExpressionClassifier formals_classifier;
+      ParserFormalParameters formals(scope);
+      Checkpoint checkpoint(this);
+      {
+        // Parsing patterns as variable reference expression creates
+        // NewUnresolved references in current scope. Entrer arrow function
+        // scope for formal parameter parsing.
+        BlockState block_state(&scope_, scope);
+        if (Check(Token::LPAREN)) {
+          // '(' StrictFormalParameters ')'
+          ParseFormalParameterList(&formals, &formals_classifier, &ok);
+          if (ok) ok = Check(Token::RPAREN);
+        } else {
+          // BindingIdentifier
+          ParseFormalParameter(&formals, &formals_classifier, &ok);
+          if (ok) {
+            DeclareFormalParameter(formals.scope, formals.at(0),
+                                   &formals_classifier);
+          }
+        }
+      }
+
+      if (ok) {
+        checkpoint.Restore(&formals.materialized_literals_count);
+        // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
+        // not be observable, or else the preparser would have failed.
+        Expression* expression =
+            ParseArrowFunctionLiteral(true, formals, formals_classifier, &ok);
+        if (ok) {
+          // Scanning must end at the same position that was recorded
+          // previously. If not, parsing has been interrupted due to a stack
+          // overflow, at which point the partially parsed arrow function
+          // concise body happens to be a valid expression. This is a problem
+          // only for arrow functions with single expression bodies, since there
+          // is no end token such as "}" for normal functions.
+          if (scanner()->location().end_pos == shared_info->end_position()) {
+            // The pre-parser saw an arrow function here, so the full parser
+            // must produce a FunctionLiteral.
+            DCHECK(expression->IsFunctionLiteral());
+            result = expression->AsFunctionLiteral();
+          } else {
+            ok = false;
+          }
+        }
+      }
+    } else if (shared_info->is_default_constructor()) {
+      result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()),
+                                  scope, shared_info->start_position(),
+                                  shared_info->end_position(),
+                                  shared_info->language_mode());
+    } else {
+      result = ParseFunctionLiteral(
+          raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck,
+          shared_info->kind(), RelocInfo::kNoPosition, function_type,
+          FunctionLiteral::kNormalArity, shared_info->language_mode(), &ok);
+    }
+    // Make sure the results agree.
+    DCHECK(ok == (result != NULL));
+  }
+
+  // Make sure the target stack is empty.
+  DCHECK(target_stack_ == NULL);
+
+  if (result != NULL) {
+    Handle<String> inferred_name(shared_info->inferred_name());
+    result->set_inferred_name(inferred_name);
+  }
+  return result;
+}
+
+
+void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
+                                 bool* ok) {
+  // StatementList ::
+  //   (StatementListItem)* <end_token>
+
+  // Allocate a target stack to use for this set of source
+  // elements. This way, all scripts and functions get their own
+  // target stack thus avoiding illegal breaks and continues across
+  // functions.
+  TargetScope scope(&this->target_stack_);
+
+  DCHECK(body != NULL);
+  bool directive_prologue = true;     // Parsing directive prologue.
+
+  while (peek() != end_token) {
+    if (directive_prologue && peek() != Token::STRING) {
+      directive_prologue = false;
+    }
+
+    Scanner::Location token_loc = scanner()->peek_location();
+    Scanner::Location old_this_loc = function_state_->this_location();
+    Scanner::Location old_super_loc = function_state_->super_location();
+    Statement* stat = ParseStatementListItem(CHECK_OK);
+
+    if (is_strong(language_mode()) && scope_->is_function_scope() &&
+        IsClassConstructor(function_state_->kind())) {
+      Scanner::Location this_loc = function_state_->this_location();
+      Scanner::Location super_loc = function_state_->super_location();
+      if (this_loc.beg_pos != old_this_loc.beg_pos &&
+          this_loc.beg_pos != token_loc.beg_pos) {
+        ReportMessageAt(this_loc, MessageTemplate::kStrongConstructorThis);
+        *ok = false;
+        return nullptr;
+      }
+      if (super_loc.beg_pos != old_super_loc.beg_pos &&
+          super_loc.beg_pos != token_loc.beg_pos) {
+        ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper);
+        *ok = false;
+        return nullptr;
+      }
+    }
+
+    if (stat == NULL || stat->IsEmpty()) {
+      directive_prologue = false;   // End of directive prologue.
+      continue;
+    }
+
+    if (directive_prologue) {
+      // A shot at a directive.
+      ExpressionStatement* e_stat;
+      Literal* literal;
+      // Still processing directive prologue?
+      if ((e_stat = stat->AsExpressionStatement()) != NULL &&
+          (literal = e_stat->expression()->AsLiteral()) != NULL &&
+          literal->raw_value()->IsString()) {
+        // Check "use strict" directive (ES5 14.1), "use asm" directive, and
+        // "use strong" directive (experimental).
+        bool use_strict_found =
+            literal->raw_value()->AsString() ==
+                ast_value_factory()->use_strict_string() &&
+            token_loc.end_pos - token_loc.beg_pos ==
+                ast_value_factory()->use_strict_string()->length() + 2;
+        bool use_strong_found =
+            allow_strong_mode() &&
+            literal->raw_value()->AsString() ==
+                ast_value_factory()->use_strong_string() &&
+            token_loc.end_pos - token_loc.beg_pos ==
+                ast_value_factory()->use_strong_string()->length() + 2;
+        if (use_strict_found || use_strong_found) {
+          // Strong mode implies strict mode. If there are several "use strict"
+          // / "use strong" directives, do the strict mode changes only once.
+          if (is_sloppy(scope_->language_mode())) {
+            RaiseLanguageMode(STRICT);
+          }
+
+          if (use_strong_found) {
+            RaiseLanguageMode(STRONG);
+            if (IsClassConstructor(function_state_->kind())) {
+              // "use strong" cannot occur in a class constructor body, to avoid
+              // unintuitive strong class object semantics.
+              ParserTraits::ReportMessageAt(
+                  token_loc, MessageTemplate::kStrongConstructorDirective);
+              *ok = false;
+              return nullptr;
+            }
+          }
+          if (!scope_->HasSimpleParameters()) {
+            // TC39 deemed "use strict" directives to be an error when occurring
+            // in the body of a function with non-simple parameter list, on
+            // 29/7/2015. https://goo.gl/ueA7Ln
+            //
+            // In V8, this also applies to "use strong " directives.
+            const AstRawString* string = literal->raw_value()->AsString();
+            ParserTraits::ReportMessageAt(
+                token_loc, MessageTemplate::kIllegalLanguageModeDirective,
+                string);
+            *ok = false;
+            return nullptr;
+          }
+          // Because declarations in strict eval code don't leak into the scope
+          // of the eval call, it is likely that functions declared in strict
+          // eval code will be used within the eval code, so lazy parsing is
+          // probably not a win.
+          if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY;
+        } else if (literal->raw_value()->AsString() ==
+                       ast_value_factory()->use_asm_string() &&
+                   token_loc.end_pos - token_loc.beg_pos ==
+                       ast_value_factory()->use_asm_string()->length() + 2) {
+          // Store the usage count; The actual use counter on the isolate is
+          // incremented after parsing is done.
+          ++use_counts_[v8::Isolate::kUseAsm];
+          scope_->SetAsmModule();
+        } else {
+          // Should not change mode, but will increment UseCounter
+          // if appropriate. Ditto usages below.
+          RaiseLanguageMode(SLOPPY);
+        }
+      } else {
+        // End of the directive prologue.
+        directive_prologue = false;
+        RaiseLanguageMode(SLOPPY);
+      }
+    } else {
+      RaiseLanguageMode(SLOPPY);
+    }
+
+    body->Add(stat, zone());
+  }
+
+  return 0;
+}
+
+
+Statement* Parser::ParseStatementListItem(bool* ok) {
+  // (Ecma 262 6th Edition, 13.1):
+  // StatementListItem:
+  //    Statement
+  //    Declaration
+
+  if (peek() != Token::CLASS) {
+    // No more classes follow; reset the start position for the consecutive
+    // class declaration group.
+    scope_->set_class_declaration_group_start(-1);
+  }
+
+  switch (peek()) {
+    case Token::FUNCTION:
+      return ParseFunctionDeclaration(NULL, ok);
+    case Token::CLASS:
+      if (scope_->class_declaration_group_start() < 0) {
+        scope_->set_class_declaration_group_start(
+            scanner()->peek_location().beg_pos);
+      }
+      return ParseClassDeclaration(NULL, ok);
+    case Token::CONST:
+      if (allow_const()) {
+        return ParseVariableStatement(kStatementListItem, NULL, ok);
+      }
+      break;
+    case Token::VAR:
+      return ParseVariableStatement(kStatementListItem, NULL, ok);
+    case Token::LET:
+      if (IsNextLetKeyword()) {
+        return ParseVariableStatement(kStatementListItem, NULL, ok);
+      }
+      break;
+    default:
+      break;
+  }
+  return ParseStatement(NULL, ok);
+}
+
+
+Statement* Parser::ParseModuleItem(bool* ok) {
+  // (Ecma 262 6th Edition, 15.2):
+  // ModuleItem :
+  //    ImportDeclaration
+  //    ExportDeclaration
+  //    StatementListItem
+
+  switch (peek()) {
+    case Token::IMPORT:
+      return ParseImportDeclaration(ok);
+    case Token::EXPORT:
+      return ParseExportDeclaration(ok);
+    default:
+      return ParseStatementListItem(ok);
+  }
+}
+
+
+void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
+  // (Ecma 262 6th Edition, 15.2):
+  // Module :
+  //    ModuleBody?
+  //
+  // ModuleBody :
+  //    ModuleItem*
+
+  DCHECK(scope_->is_module_scope());
+  RaiseLanguageMode(STRICT);
+
+  while (peek() != Token::EOS) {
+    Statement* stat = ParseModuleItem(CHECK_OK);
+    if (stat && !stat->IsEmpty()) {
+      body->Add(stat, zone());
+    }
+  }
+
+  // Check that all exports are bound.
+  ModuleDescriptor* descriptor = scope_->module();
+  for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
+       it.Advance()) {
+    if (scope_->LookupLocal(it.local_name()) == NULL) {
+      // TODO(adamk): Pass both local_name and export_name once ParserTraits
+      // supports multiple arg error messages.
+      // Also try to report this at a better location.
+      ParserTraits::ReportMessage(MessageTemplate::kModuleExportUndefined,
+                                  it.local_name());
+      *ok = false;
+      return NULL;
+    }
+  }
+
+  scope_->module()->Freeze();
+  return NULL;
+}
+
+
+const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
+  // ModuleSpecifier :
+  //    StringLiteral
+
+  Expect(Token::STRING, CHECK_OK);
+  return GetSymbol(scanner());
+}
+
+
+void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
+                                ZoneList<Scanner::Location>* export_locations,
+                                ZoneList<const AstRawString*>* local_names,
+                                Scanner::Location* reserved_loc, bool* ok) {
+  // ExportClause :
+  //   '{' '}'
+  //   '{' ExportsList '}'
+  //   '{' ExportsList ',' '}'
+  //
+  // ExportsList :
+  //   ExportSpecifier
+  //   ExportsList ',' ExportSpecifier
+  //
+  // ExportSpecifier :
+  //   IdentifierName
+  //   IdentifierName 'as' IdentifierName
+
+  Expect(Token::LBRACE, CHECK_OK);
+
+  Token::Value name_tok;
+  while ((name_tok = peek()) != Token::RBRACE) {
+    // Keep track of the first reserved word encountered in case our
+    // caller needs to report an error.
+    if (!reserved_loc->IsValid() &&
+        !Token::IsIdentifier(name_tok, STRICT, false)) {
+      *reserved_loc = scanner()->location();
+    }
+    const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
+    const AstRawString* export_name = NULL;
+    if (CheckContextualKeyword(CStrVector("as"))) {
+      export_name = ParseIdentifierName(CHECK_OK);
+    }
+    if (export_name == NULL) {
+      export_name = local_name;
+    }
+    export_names->Add(export_name, zone());
+    local_names->Add(local_name, zone());
+    export_locations->Add(scanner()->location(), zone());
+    if (peek() == Token::RBRACE) break;
+    Expect(Token::COMMA, CHECK_OK);
+  }
+
+  Expect(Token::RBRACE, CHECK_OK);
+
+  return 0;
+}
+
+
+ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) {
+  // NamedImports :
+  //   '{' '}'
+  //   '{' ImportsList '}'
+  //   '{' ImportsList ',' '}'
+  //
+  // ImportsList :
+  //   ImportSpecifier
+  //   ImportsList ',' ImportSpecifier
+  //
+  // ImportSpecifier :
+  //   BindingIdentifier
+  //   IdentifierName 'as' BindingIdentifier
+
+  Expect(Token::LBRACE, CHECK_OK);
+
+  ZoneList<ImportDeclaration*>* result =
+      new (zone()) ZoneList<ImportDeclaration*>(1, zone());
+  while (peek() != Token::RBRACE) {
+    const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
+    const AstRawString* local_name = import_name;
+    // In the presence of 'as', the left-side of the 'as' can
+    // be any IdentifierName. But without 'as', it must be a valid
+    // BindingIdentifier.
+    if (CheckContextualKeyword(CStrVector("as"))) {
+      local_name = ParseIdentifierName(CHECK_OK);
+    }
+    if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false)) {
+      *ok = false;
+      ReportMessage(MessageTemplate::kUnexpectedReserved);
+      return NULL;
+    } else if (IsEvalOrArguments(local_name)) {
+      *ok = false;
+      ReportMessage(MessageTemplate::kStrictEvalArguments);
+      return NULL;
+    } else if (is_strong(language_mode()) && IsUndefined(local_name)) {
+      *ok = false;
+      ReportMessage(MessageTemplate::kStrongUndefined);
+      return NULL;
+    }
+    VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
+    ImportDeclaration* declaration =
+        factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
+    Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
+    result->Add(declaration, zone());
+    if (peek() == Token::RBRACE) break;
+    Expect(Token::COMMA, CHECK_OK);
+  }
+
+  Expect(Token::RBRACE, CHECK_OK);
+
+  return result;
+}
+
+
+Statement* Parser::ParseImportDeclaration(bool* ok) {
+  // ImportDeclaration :
+  //   'import' ImportClause 'from' ModuleSpecifier ';'
+  //   'import' ModuleSpecifier ';'
+  //
+  // ImportClause :
+  //   NameSpaceImport
+  //   NamedImports
+  //   ImportedDefaultBinding
+  //   ImportedDefaultBinding ',' NameSpaceImport
+  //   ImportedDefaultBinding ',' NamedImports
+  //
+  // NameSpaceImport :
+  //   '*' 'as' ImportedBinding
+
+  int pos = peek_position();
+  Expect(Token::IMPORT, CHECK_OK);
+
+  Token::Value tok = peek();
+
+  // 'import' ModuleSpecifier ';'
+  if (tok == Token::STRING) {
+    const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
+    scope_->module()->AddModuleRequest(module_specifier, zone());
+    ExpectSemicolon(CHECK_OK);
+    return factory()->NewEmptyStatement(pos);
+  }
+
+  // Parse ImportedDefaultBinding if present.
+  ImportDeclaration* import_default_declaration = NULL;
+  if (tok != Token::MUL && tok != Token::LBRACE) {
+    const AstRawString* local_name =
+        ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
+    VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
+    import_default_declaration = factory()->NewImportDeclaration(
+        proxy, ast_value_factory()->default_string(), NULL, scope_, pos);
+    Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true,
+            CHECK_OK);
+  }
+
+  const AstRawString* module_instance_binding = NULL;
+  ZoneList<ImportDeclaration*>* named_declarations = NULL;
+  if (import_default_declaration == NULL || Check(Token::COMMA)) {
+    switch (peek()) {
+      case Token::MUL: {
+        Consume(Token::MUL);
+        ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
+        module_instance_binding =
+            ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
+        // TODO(ES6): Add an appropriate declaration.
+        break;
+      }
+
+      case Token::LBRACE:
+        named_declarations = ParseNamedImports(pos, CHECK_OK);
+        break;
+
+      default:
+        *ok = false;
+        ReportUnexpectedToken(scanner()->current_token());
+        return NULL;
+    }
+  }
+
+  ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
+  const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
+  scope_->module()->AddModuleRequest(module_specifier, zone());
+
+  if (module_instance_binding != NULL) {
+    // TODO(ES6): Set the module specifier for the module namespace binding.
+  }
+
+  if (import_default_declaration != NULL) {
+    import_default_declaration->set_module_specifier(module_specifier);
+  }
+
+  if (named_declarations != NULL) {
+    for (int i = 0; i < named_declarations->length(); ++i) {
+      named_declarations->at(i)->set_module_specifier(module_specifier);
+    }
+  }
+
+  ExpectSemicolon(CHECK_OK);
+  return factory()->NewEmptyStatement(pos);
+}
+
+
+Statement* Parser::ParseExportDefault(bool* ok) {
+  //  Supports the following productions, starting after the 'default' token:
+  //    'export' 'default' FunctionDeclaration
+  //    'export' 'default' ClassDeclaration
+  //    'export' 'default' AssignmentExpression[In] ';'
+
+  Expect(Token::DEFAULT, CHECK_OK);
+  Scanner::Location default_loc = scanner()->location();
+
+  ZoneList<const AstRawString*> names(1, zone());
+  Statement* result = NULL;
+  switch (peek()) {
+    case Token::FUNCTION:
+      // TODO(ES6): Support parsing anonymous function declarations here.
+      result = ParseFunctionDeclaration(&names, CHECK_OK);
+      break;
+
+    case Token::CLASS:
+      // TODO(ES6): Support parsing anonymous class declarations here.
+      result = ParseClassDeclaration(&names, CHECK_OK);
+      break;
+
+    default: {
+      int pos = peek_position();
+      ExpressionClassifier classifier;
+      Expression* expr = ParseAssignmentExpression(true, &classifier, CHECK_OK);
+      expr = ParserTraits::RewriteNonPattern(expr, &classifier, CHECK_OK);
+
+      ExpectSemicolon(CHECK_OK);
+      result = factory()->NewExpressionStatement(expr, pos);
+      break;
+    }
+  }
+
+  const AstRawString* default_string = ast_value_factory()->default_string();
+
+  DCHECK_LE(names.length(), 1);
+  if (names.length() == 1) {
+    scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok);
+    if (!*ok) {
+      ParserTraits::ReportMessageAt(
+          default_loc, MessageTemplate::kDuplicateExport, default_string);
+      return NULL;
+    }
+  } else {
+    // TODO(ES6): Assign result to a const binding with the name "*default*"
+    // and add an export entry with "*default*" as the local name.
+  }
+
+  return result;
+}
+
+
+Statement* Parser::ParseExportDeclaration(bool* ok) {
+  // ExportDeclaration:
+  //    'export' '*' 'from' ModuleSpecifier ';'
+  //    'export' ExportClause ('from' ModuleSpecifier)? ';'
+  //    'export' VariableStatement
+  //    'export' Declaration
+  //    'export' 'default' ... (handled in ParseExportDefault)
+
+  int pos = peek_position();
+  Expect(Token::EXPORT, CHECK_OK);
+
+  Statement* result = NULL;
+  ZoneList<const AstRawString*> names(1, zone());
+  switch (peek()) {
+    case Token::DEFAULT:
+      return ParseExportDefault(ok);
+
+    case Token::MUL: {
+      Consume(Token::MUL);
+      ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
+      const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
+      scope_->module()->AddModuleRequest(module_specifier, zone());
+      // TODO(ES6): scope_->module()->AddStarExport(...)
+      ExpectSemicolon(CHECK_OK);
+      return factory()->NewEmptyStatement(pos);
+    }
+
+    case Token::LBRACE: {
+      // There are two cases here:
+      //
+      // 'export' ExportClause ';'
+      // and
+      // 'export' ExportClause FromClause ';'
+      //
+      // In the first case, the exported identifiers in ExportClause must
+      // not be reserved words, while in the latter they may be. We
+      // pass in a location that gets filled with the first reserved word
+      // encountered, and then throw a SyntaxError if we are in the
+      // non-FromClause case.
+      Scanner::Location reserved_loc = Scanner::Location::invalid();
+      ZoneList<const AstRawString*> export_names(1, zone());
+      ZoneList<Scanner::Location> export_locations(1, zone());
+      ZoneList<const AstRawString*> local_names(1, zone());
+      ParseExportClause(&export_names, &export_locations, &local_names,
+                        &reserved_loc, CHECK_OK);
+      const AstRawString* indirect_export_module_specifier = NULL;
+      if (CheckContextualKeyword(CStrVector("from"))) {
+        indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
+      } else if (reserved_loc.IsValid()) {
+        // No FromClause, so reserved words are invalid in ExportClause.
+        *ok = false;
+        ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
+        return NULL;
+      }
+      ExpectSemicolon(CHECK_OK);
+      const int length = export_names.length();
+      DCHECK_EQ(length, local_names.length());
+      DCHECK_EQ(length, export_locations.length());
+      if (indirect_export_module_specifier == NULL) {
+        for (int i = 0; i < length; ++i) {
+          scope_->module()->AddLocalExport(export_names[i], local_names[i],
+                                           zone(), ok);
+          if (!*ok) {
+            ParserTraits::ReportMessageAt(export_locations[i],
+                                          MessageTemplate::kDuplicateExport,
+                                          export_names[i]);
+            return NULL;
+          }
+        }
+      } else {
+        scope_->module()->AddModuleRequest(indirect_export_module_specifier,
+                                           zone());
+        for (int i = 0; i < length; ++i) {
+          // TODO(ES6): scope_->module()->AddIndirectExport(...);(
+        }
+      }
+      return factory()->NewEmptyStatement(pos);
+    }
+
+    case Token::FUNCTION:
+      result = ParseFunctionDeclaration(&names, CHECK_OK);
+      break;
+
+    case Token::CLASS:
+      result = ParseClassDeclaration(&names, CHECK_OK);
+      break;
+
+    case Token::VAR:
+    case Token::LET:
+    case Token::CONST:
+      result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
+      break;
+
+    default:
+      *ok = false;
+      ReportUnexpectedToken(scanner()->current_token());
+      return NULL;
+  }
+
+  // Extract declared names into export declarations.
+  ModuleDescriptor* descriptor = scope_->module();
+  for (int i = 0; i < names.length(); ++i) {
+    descriptor->AddLocalExport(names[i], names[i], zone(), ok);
+    if (!*ok) {
+      // TODO(adamk): Possibly report this error at the right place.
+      ParserTraits::ReportMessage(MessageTemplate::kDuplicateExport, names[i]);
+      return NULL;
+    }
+  }
+
+  DCHECK_NOT_NULL(result);
+  return result;
+}
+
+
+Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
+                                  bool* ok) {
+  // Statement ::
+  //   EmptyStatement
+  //   ...
+
+  if (peek() == Token::SEMICOLON) {
+    Next();
+    return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
+  }
+  return ParseSubStatement(labels, ok);
+}
+
+
+Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels,
+                                     bool* ok) {
+  // Statement ::
+  //   Block
+  //   VariableStatement
+  //   EmptyStatement
+  //   ExpressionStatement
+  //   IfStatement
+  //   IterationStatement
+  //   ContinueStatement
+  //   BreakStatement
+  //   ReturnStatement
+  //   WithStatement
+  //   LabelledStatement
+  //   SwitchStatement
+  //   ThrowStatement
+  //   TryStatement
+  //   DebuggerStatement
+
+  // Note: Since labels can only be used by 'break' and 'continue'
+  // statements, which themselves are only valid within blocks,
+  // iterations or 'switch' statements (i.e., BreakableStatements),
+  // labels can be simply ignored in all other cases; except for
+  // trivial labeled break statements 'label: break label' which is
+  // parsed into an empty statement.
+  switch (peek()) {
+    case Token::LBRACE:
+      return ParseBlock(labels, ok);
+
+    case Token::SEMICOLON:
+      if (is_strong(language_mode())) {
+        ReportMessageAt(scanner()->peek_location(),
+                        MessageTemplate::kStrongEmpty);
+        *ok = false;
+        return NULL;
+      }
+      Next();
+      return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
+
+    case Token::IF:
+      return ParseIfStatement(labels, ok);
+
+    case Token::DO:
+      return ParseDoWhileStatement(labels, ok);
+
+    case Token::WHILE:
+      return ParseWhileStatement(labels, ok);
+
+    case Token::FOR:
+      return ParseForStatement(labels, ok);
+
+    case Token::CONTINUE:
+    case Token::BREAK:
+    case Token::RETURN:
+    case Token::THROW:
+    case Token::TRY: {
+      // These statements must have their labels preserved in an enclosing
+      // block
+      if (labels == NULL) {
+        return ParseStatementAsUnlabelled(labels, ok);
+      } else {
+        Block* result =
+            factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
+        Target target(&this->target_stack_, result);
+        Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
+        if (result) result->statements()->Add(statement, zone());
+        return result;
+      }
+    }
+
+    case Token::WITH:
+      return ParseWithStatement(labels, ok);
+
+    case Token::SWITCH:
+      return ParseSwitchStatement(labels, ok);
+
+    case Token::FUNCTION: {
+      // FunctionDeclaration is only allowed in the context of SourceElements
+      // (Ecma 262 5th Edition, clause 14):
+      // SourceElement:
+      //    Statement
+      //    FunctionDeclaration
+      // Common language extension is to allow function declaration in place
+      // of any statement. This language extension is disabled in strict mode.
+      //
+      // In Harmony mode, this case also handles the extension:
+      // Statement:
+      //    GeneratorDeclaration
+      if (is_strict(language_mode())) {
+        ReportMessageAt(scanner()->peek_location(),
+                        MessageTemplate::kStrictFunction);
+        *ok = false;
+        return NULL;
+      }
+      return ParseFunctionDeclaration(NULL, ok);
+    }
+
+    case Token::DEBUGGER:
+      return ParseDebuggerStatement(ok);
+
+    case Token::VAR:
+      return ParseVariableStatement(kStatement, NULL, ok);
+
+    case Token::CONST:
+      // In ES6 CONST is not allowed as a Statement, only as a
+      // LexicalDeclaration, however we continue to allow it in sloppy mode for
+      // backwards compatibility.
+      if (is_sloppy(language_mode()) && allow_legacy_const()) {
+        return ParseVariableStatement(kStatement, NULL, ok);
+      }
+
+    // Fall through.
+    default:
+      return ParseExpressionOrLabelledStatement(labels, ok);
+  }
+}
+
+Statement* Parser::ParseStatementAsUnlabelled(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
+  switch (peek()) {
+    case Token::CONTINUE:
+      return ParseContinueStatement(ok);
+
+    case Token::BREAK:
+      return ParseBreakStatement(labels, ok);
+
+    case Token::RETURN:
+      return ParseReturnStatement(ok);
+
+    case Token::THROW:
+      return ParseThrowStatement(ok);
+
+    case Token::TRY:
+      return ParseTryStatement(ok);
+
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+}
+
+
+VariableProxy* Parser::NewUnresolved(const AstRawString* name,
+                                     VariableMode mode) {
+  // If we are inside a function, a declaration of a var/const variable is a
+  // truly local variable, and the scope of the variable is always the function
+  // scope.
+  // Let/const variables in harmony mode are always added to the immediately
+  // enclosing scope.
+  Scope* scope =
+      IsLexicalVariableMode(mode) ? scope_ : scope_->DeclarationScope();
+  return scope->NewUnresolved(factory(), name, Variable::NORMAL,
+                              scanner()->location().beg_pos,
+                              scanner()->location().end_pos);
+}
+
+
+Variable* Parser::Declare(Declaration* declaration,
+                          DeclarationDescriptor::Kind declaration_kind,
+                          bool resolve, bool* ok, Scope* scope) {
+  VariableProxy* proxy = declaration->proxy();
+  DCHECK(proxy->raw_name() != NULL);
+  const AstRawString* name = proxy->raw_name();
+  VariableMode mode = declaration->mode();
+  bool is_function_declaration = declaration->IsFunctionDeclaration();
+  if (scope == nullptr) scope = scope_;
+  Scope* declaration_scope =
+      IsLexicalVariableMode(mode) ? scope : scope->DeclarationScope();
+  Variable* var = NULL;
+
+  // If a suitable scope exists, then we can statically declare this
+  // variable and also set its mode. In any case, a Declaration node
+  // will be added to the scope so that the declaration can be added
+  // to the corresponding activation frame at runtime if necessary.
+  // For instance, var declarations inside a sloppy eval scope need
+  // to be added to the calling function context. Similarly, strict
+  // mode eval scope and lexical eval bindings do not leak variable
+  // declarations to the caller's scope so we declare all locals, too.
+  if (declaration_scope->is_function_scope() ||
+      declaration_scope->is_block_scope() ||
+      declaration_scope->is_module_scope() ||
+      declaration_scope->is_script_scope() ||
+      (declaration_scope->is_eval_scope() &&
+       (is_strict(declaration_scope->language_mode()) ||
+        IsLexicalVariableMode(mode)))) {
+    // Declare the variable in the declaration scope.
+    var = declaration_scope->LookupLocal(name);
+    if (var == NULL) {
+      // Declare the name.
+      Variable::Kind kind = Variable::NORMAL;
+      int declaration_group_start = -1;
+      if (is_function_declaration) {
+        kind = Variable::FUNCTION;
+      } else if (declaration->IsVariableDeclaration() &&
+                 declaration->AsVariableDeclaration()->is_class_declaration()) {
+        kind = Variable::CLASS;
+        declaration_group_start =
+            declaration->AsVariableDeclaration()->declaration_group_start();
+      }
+      var = declaration_scope->DeclareLocal(
+          name, mode, declaration->initialization(), kind, kNotAssigned,
+          declaration_group_start);
+    } else if (((IsLexicalVariableMode(mode) ||
+                 IsLexicalVariableMode(var->mode())) &&
+                // Allow duplicate function decls for web compat, see bug 4693.
+                (is_strict(language_mode()) || !is_function_declaration ||
+                 !var->is_function())) ||
+               ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) &&
+                !declaration_scope->is_script_scope())) {
+      // The name was declared in this scope before; check for conflicting
+      // re-declarations. We have a conflict if either of the declarations is
+      // not a var (in script scope, we also have to ignore legacy const for
+      // compatibility). There is similar code in runtime.cc in the Declare
+      // functions. The function CheckConflictingVarDeclarations checks for
+      // var and let bindings from different scopes whereas this is a check for
+      // conflicting declarations within the same scope. This check also covers
+      // the special case
+      //
+      // function () { let x; { var x; } }
+      //
+      // because the var declaration is hoisted to the function scope where 'x'
+      // is already bound.
+      DCHECK(IsDeclaredVariableMode(var->mode()));
+      if (is_strict(language_mode()) ||
+          (allow_harmony_sloppy() && mode != CONST_LEGACY &&
+           var->mode() != CONST_LEGACY)) {
+        // In harmony we treat re-declarations as early errors. See
+        // ES5 16 for a definition of early errors.
+        if (declaration_kind == DeclarationDescriptor::NORMAL) {
+          ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
+        } else {
+          ParserTraits::ReportMessage(MessageTemplate::kParamDupe);
+        }
+        *ok = false;
+        return nullptr;
+      }
+      Expression* expression = NewThrowSyntaxError(
+          MessageTemplate::kVarRedeclaration, name, declaration->position());
+      declaration_scope->SetIllegalRedeclaration(expression);
+    } else if (mode == VAR) {
+      var->set_maybe_assigned();
+    }
+  } else if (declaration_scope->is_eval_scope() &&
+             is_sloppy(declaration_scope->language_mode()) &&
+             !IsLexicalVariableMode(mode)) {
+    // In a var binding in a sloppy direct eval, pollute the enclosing scope
+    // with this new binding by doing the following:
+    // The proxy is bound to a lookup variable to force a dynamic declaration
+    // using the DeclareLookupSlot runtime function.
+    Variable::Kind kind = Variable::NORMAL;
+    // TODO(sigurds) figure out if kNotAssigned is OK here
+    var = new (zone()) Variable(declaration_scope, name, mode, kind,
+                                declaration->initialization(), kNotAssigned);
+    var->AllocateTo(VariableLocation::LOOKUP, -1);
+    var->SetFromEval();
+    resolve = true;
+  }
+
+
+  // We add a declaration node for every declaration. The compiler
+  // will only generate code if necessary. In particular, declarations
+  // for inner local variables that do not represent functions won't
+  // result in any generated code.
+  //
+  // Note that we always add an unresolved proxy even if it's not
+  // used, simply because we don't know in this method (w/o extra
+  // parameters) if the proxy is needed or not. The proxy will be
+  // bound during variable resolution time unless it was pre-bound
+  // below.
+  //
+  // WARNING: This will lead to multiple declaration nodes for the
+  // same variable if it is declared several times. This is not a
+  // semantic issue as long as we keep the source order, but it may be
+  // a performance issue since it may lead to repeated
+  // RuntimeHidden_DeclareLookupSlot calls.
+  declaration_scope->AddDeclaration(declaration);
+
+  if (mode == CONST_LEGACY && declaration_scope->is_script_scope()) {
+    // For global const variables we bind the proxy to a variable.
+    DCHECK(resolve);  // should be set by all callers
+    Variable::Kind kind = Variable::NORMAL;
+    var = new (zone()) Variable(declaration_scope, name, mode, kind,
+                                kNeedsInitialization, kNotAssigned);
+  }
+
+  // If requested and we have a local variable, bind the proxy to the variable
+  // at parse-time. This is used for functions (and consts) declared inside
+  // statements: the corresponding function (or const) variable must be in the
+  // function scope and not a statement-local scope, e.g. as provided with a
+  // 'with' statement:
+  //
+  //   with (obj) {
+  //     function f() {}
+  //   }
+  //
+  // which is translated into:
+  //
+  //   with (obj) {
+  //     // in this case this is not: 'var f; f = function () {};'
+  //     var f = function () {};
+  //   }
+  //
+  // Note that if 'f' is accessed from inside the 'with' statement, it
+  // will be allocated in the context (because we must be able to look
+  // it up dynamically) but it will also be accessed statically, i.e.,
+  // with a context slot index and a context chain length for this
+  // initialization code. Thus, inside the 'with' statement, we need
+  // both access to the static and the dynamic context chain; the
+  // runtime needs to provide both.
+  if (resolve && var != NULL) {
+    proxy->BindTo(var);
+  }
+  return var;
+}
+
+
+// Language extension which is only enabled for source files loaded
+// through the API's extension mechanism.  A native function
+// declaration is resolved by looking up the function through a
+// callback provided by the extension.
+Statement* Parser::ParseNativeDeclaration(bool* ok) {
+  int pos = peek_position();
+  Expect(Token::FUNCTION, CHECK_OK);
+  // Allow "eval" or "arguments" for backward compatibility.
+  const AstRawString* name =
+      ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  bool done = (peek() == Token::RPAREN);
+  while (!done) {
+    ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+    done = (peek() == Token::RPAREN);
+    if (!done) {
+      Expect(Token::COMMA, CHECK_OK);
+    }
+  }
+  Expect(Token::RPAREN, CHECK_OK);
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  // Make sure that the function containing the native declaration
+  // isn't lazily compiled. The extension structures are only
+  // accessible while parsing the first time not when reparsing
+  // because of lazy compilation.
+  // TODO(adamk): Should this be ClosureScope()?
+  scope_->DeclarationScope()->ForceEagerCompilation();
+
+  // TODO(1240846): It's weird that native function declarations are
+  // introduced dynamically when we meet their declarations, whereas
+  // other functions are set up when entering the surrounding scope.
+  VariableProxy* proxy = NewUnresolved(name, VAR);
+  Declaration* declaration =
+      factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
+  Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
+  NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
+      name, extension_, RelocInfo::kNoPosition);
+  return factory()->NewExpressionStatement(
+      factory()->NewAssignment(Token::INIT, proxy, lit, RelocInfo::kNoPosition),
+      pos);
+}
+
+
+Statement* Parser::ParseFunctionDeclaration(
+    ZoneList<const AstRawString*>* names, bool* ok) {
+  // FunctionDeclaration ::
+  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
+  // GeneratorDeclaration ::
+  //   'function' '*' Identifier '(' FormalParameterListopt ')'
+  //      '{' FunctionBody '}'
+  Expect(Token::FUNCTION, CHECK_OK);
+  int pos = position();
+  bool is_generator = Check(Token::MUL);
+  bool is_strict_reserved = false;
+  const AstRawString* name = ParseIdentifierOrStrictReservedWord(
+      &is_strict_reserved, CHECK_OK);
+
+  FuncNameInferrer::State fni_state(fni_);
+  if (fni_ != NULL) fni_->PushEnclosingName(name);
+  FunctionLiteral* fun = ParseFunctionLiteral(
+      name, scanner()->location(),
+      is_strict_reserved ? kFunctionNameIsStrictReserved
+                         : kFunctionNameValidityUnknown,
+      is_generator ? FunctionKind::kGeneratorFunction
+                   : FunctionKind::kNormalFunction,
+      pos, FunctionLiteral::kDeclaration, FunctionLiteral::kNormalArity,
+      language_mode(), CHECK_OK);
+
+  // Even if we're not at the top-level of the global or a function
+  // scope, we treat it as such and introduce the function with its
+  // initial value upon entering the corresponding scope.
+  // In ES6, a function behaves as a lexical binding, except in
+  // a script scope, or the initial scope of eval or another function.
+  VariableMode mode =
+      is_strong(language_mode())
+          ? CONST
+          : (is_strict(language_mode()) || allow_harmony_sloppy_function()) &&
+                    !scope_->is_declaration_scope()
+                ? LET
+                : VAR;
+  VariableProxy* proxy = NewUnresolved(name, mode);
+  Declaration* declaration =
+      factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
+  Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
+  if (names) names->Add(name, zone());
+  EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
+  if (is_sloppy(language_mode()) && allow_harmony_sloppy_function() &&
+      !scope_->is_declaration_scope()) {
+    SloppyBlockFunctionStatement* delegate =
+        factory()->NewSloppyBlockFunctionStatement(empty, scope_);
+    scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name,
+                                                                     delegate);
+    return delegate;
+  }
+  return empty;
+}
+
+
+Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
+                                         bool* ok) {
+  // ClassDeclaration ::
+  //   'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
+  //
+  // A ClassDeclaration
+  //
+  //   class C { ... }
+  //
+  // has the same semantics as:
+  //
+  //   let C = class C { ... };
+  //
+  // so rewrite it as such.
+
+  Expect(Token::CLASS, CHECK_OK);
+  if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
+    ReportMessage(MessageTemplate::kSloppyLexical);
+    *ok = false;
+    return NULL;
+  }
+
+  int pos = position();
+  bool is_strict_reserved = false;
+  const AstRawString* name =
+      ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+  ClassLiteral* value = ParseClassLiteral(name, scanner()->location(),
+                                          is_strict_reserved, pos, CHECK_OK);
+
+  VariableMode mode = is_strong(language_mode()) ? CONST : LET;
+  VariableProxy* proxy = NewUnresolved(name, mode);
+  const bool is_class_declaration = true;
+  Declaration* declaration = factory()->NewVariableDeclaration(
+      proxy, mode, scope_, pos, is_class_declaration,
+      scope_->class_declaration_group_start());
+  Variable* outer_class_variable =
+      Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
+  proxy->var()->set_initializer_position(position());
+  // This is needed because a class ("class Name { }") creates two bindings (one
+  // in the outer scope, and one in the class scope). The method is a function
+  // scope inside the inner scope (class scope). The consecutive class
+  // declarations are in the outer scope.
+  if (value->class_variable_proxy() && value->class_variable_proxy()->var() &&
+      outer_class_variable->is_class()) {
+    // In some cases, the outer variable is not detected as a class variable;
+    // this happens e.g., for lazy methods. They are excluded from strong mode
+    // checks for now. TODO(marja, rossberg): re-create variables with the
+    // correct Kind and remove this hack.
+    value->class_variable_proxy()
+        ->var()
+        ->AsClassVariable()
+        ->set_declaration_group_start(
+            outer_class_variable->AsClassVariable()->declaration_group_start());
+  }
+
+  Assignment* assignment =
+      factory()->NewAssignment(Token::INIT, proxy, value, pos);
+  Statement* assignment_statement =
+      factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
+  if (names) names->Add(name, zone());
+  return assignment_statement;
+}
+
+
+Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels,
+                          bool finalize_block_scope, bool* ok) {
+  // The harmony mode uses block elements instead of statements.
+  //
+  // Block ::
+  //   '{' StatementList '}'
+
+  // Construct block expecting 16 statements.
+  Block* body =
+      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
+  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
+
+  // Parse the statements and collect escaping labels.
+  Expect(Token::LBRACE, CHECK_OK);
+  block_scope->set_start_position(scanner()->location().beg_pos);
+  { BlockState block_state(&scope_, block_scope);
+    Target target(&this->target_stack_, body);
+
+    while (peek() != Token::RBRACE) {
+      Statement* stat = ParseStatementListItem(CHECK_OK);
+      if (stat && !stat->IsEmpty()) {
+        body->statements()->Add(stat, zone());
+      }
+    }
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+  block_scope->set_end_position(scanner()->location().end_pos);
+  if (finalize_block_scope) {
+    block_scope = block_scope->FinalizeBlockScope();
+  }
+  body->set_scope(block_scope);
+  return body;
+}
+
+
+Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
+  return ParseBlock(labels, true, ok);
+}
+
+
+Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
+    ZoneList<const AstRawString*>* names, bool* ok) {
+  Block* result = descriptor.parser->factory()->NewBlock(
+      NULL, 1, true, descriptor.declaration_pos);
+  for (auto declaration : declarations) {
+    PatternRewriter::DeclareAndInitializeVariables(
+        result, &descriptor, &declaration, names, CHECK_OK);
+  }
+  return result;
+}
+
+
+Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
+                                      ZoneList<const AstRawString*>* names,
+                                      bool* ok) {
+  // VariableStatement ::
+  //   VariableDeclarations ';'
+
+  // The scope of a var/const declared variable anywhere inside a function
+  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
+  // transform a source-level var/const declaration into a (Function)
+  // Scope declaration, and rewrite the source-level initialization into an
+  // assignment statement. We use a block to collect multiple assignments.
+  //
+  // We mark the block as initializer block because we don't want the
+  // rewriter to add a '.result' assignment to such a block (to get compliant
+  // behavior for code such as print(eval('var x = 7')), and for cosmetic
+  // reasons when pretty-printing. Also, unless an assignment (initialization)
+  // is inside an initializer block, it is ignored.
+
+  DeclarationParsingResult parsing_result;
+  ParseVariableDeclarations(var_context, &parsing_result, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+
+  Block* result = parsing_result.BuildInitializationBlock(names, CHECK_OK);
+  return result;
+}
+
+
+void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
+                                       DeclarationParsingResult* parsing_result,
+                                       bool* ok) {
+  // VariableDeclarations ::
+  //   ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
+  //
+  // The ES6 Draft Rev3 specifies the following grammar for const declarations
+  //
+  // ConstDeclaration ::
+  //   const ConstBinding (',' ConstBinding)* ';'
+  // ConstBinding ::
+  //   Identifier '=' AssignmentExpression
+  //
+  // TODO(ES6):
+  // ConstBinding ::
+  //   BindingPattern '=' AssignmentExpression
+
+  parsing_result->descriptor.parser = this;
+  parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
+  parsing_result->descriptor.declaration_pos = peek_position();
+  parsing_result->descriptor.initialization_pos = peek_position();
+  parsing_result->descriptor.mode = VAR;
+  // True if the binding needs initialization. 'let' and 'const' declared
+  // bindings are created uninitialized by their declaration nodes and
+  // need initialization. 'var' declared bindings are always initialized
+  // immediately by their declaration nodes.
+  parsing_result->descriptor.needs_init = false;
+  if (peek() == Token::VAR) {
+    if (is_strong(language_mode())) {
+      Scanner::Location location = scanner()->peek_location();
+      ReportMessageAt(location, MessageTemplate::kStrongVar);
+      *ok = false;
+      return;
+    }
+    Consume(Token::VAR);
+  } else if (peek() == Token::CONST && allow_const()) {
+    Consume(Token::CONST);
+    if (is_sloppy(language_mode()) && allow_legacy_const()) {
+      parsing_result->descriptor.mode = CONST_LEGACY;
+      ++use_counts_[v8::Isolate::kLegacyConst];
+    } else {
+      DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
+      DCHECK(var_context != kStatement);
+      parsing_result->descriptor.mode = CONST;
+    }
+    parsing_result->descriptor.needs_init = true;
+  } else if (peek() == Token::LET && allow_let()) {
+    Consume(Token::LET);
+    DCHECK(var_context != kStatement);
+    parsing_result->descriptor.mode = LET;
+    parsing_result->descriptor.needs_init = true;
+  } else {
+    UNREACHABLE();  // by current callers
+  }
+
+  parsing_result->descriptor.scope = scope_;
+  parsing_result->descriptor.hoist_scope = nullptr;
+
+
+  bool first_declaration = true;
+  int bindings_start = peek_position();
+  bool is_for_iteration_variable;
+  do {
+    FuncNameInferrer::State fni_state(fni_);
+
+    // Parse name.
+    if (!first_declaration) Consume(Token::COMMA);
+
+    Expression* pattern;
+    int decl_pos = peek_position();
+    {
+      ExpressionClassifier pattern_classifier;
+      Token::Value next = peek();
+      pattern = ParsePrimaryExpression(&pattern_classifier, ok);
+      if (!*ok) return;
+      ValidateBindingPattern(&pattern_classifier, ok);
+      if (!*ok) return;
+      if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
+        ValidateLetPattern(&pattern_classifier, ok);
+        if (!*ok) return;
+      }
+      if (!allow_harmony_destructuring_bind() && !pattern->IsVariableProxy()) {
+        ReportUnexpectedToken(next);
+        *ok = false;
+        return;
+      }
+    }
+
+    bool is_pattern =
+        (pattern->IsObjectLiteral() || pattern->IsArrayLiteral()) &&
+        !pattern->is_parenthesized();
+
+    Scanner::Location variable_loc = scanner()->location();
+    const AstRawString* single_name =
+        pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name()
+                                   : nullptr;
+    if (single_name != nullptr) {
+      if (fni_ != NULL) fni_->PushVariableName(single_name);
+    }
+
+    is_for_iteration_variable =
+        var_context == kForStatement &&
+        (peek() == Token::IN || PeekContextualKeyword(CStrVector("of")));
+    if (is_for_iteration_variable &&
+        (parsing_result->descriptor.mode == CONST ||
+         parsing_result->descriptor.mode == CONST_LEGACY)) {
+      parsing_result->descriptor.needs_init = false;
+    }
+
+    Expression* value = NULL;
+    // Harmony consts have non-optional initializers.
+    int initializer_position = RelocInfo::kNoPosition;
+    if (Check(Token::ASSIGN)) {
+      ExpressionClassifier classifier;
+      value = ParseAssignmentExpression(var_context != kForStatement,
+                                        &classifier, ok);
+      if (!*ok) return;
+      value = ParserTraits::RewriteNonPattern(value, &classifier, ok);
+      if (!*ok) return;
+      variable_loc.end_pos = scanner()->location().end_pos;
+
+      if (!parsing_result->first_initializer_loc.IsValid()) {
+        parsing_result->first_initializer_loc = variable_loc;
+      }
+
+      // Don't infer if it is "a = function(){...}();"-like expression.
+      if (single_name) {
+        if (fni_ != NULL && value->AsCall() == NULL &&
+            value->AsCallNew() == NULL) {
+          fni_->Infer();
+        } else {
+          fni_->RemoveLastFunction();
+        }
+      }
+
+      if (allow_harmony_function_name() && single_name) {
+        if (value->IsFunctionLiteral()) {
+          auto function_literal = value->AsFunctionLiteral();
+          if (function_literal->is_anonymous()) {
+            function_literal->set_raw_name(single_name);
+          }
+        } else if (value->IsClassLiteral()) {
+          auto class_literal = value->AsClassLiteral();
+          if (class_literal->raw_name() == nullptr) {
+            class_literal->set_raw_name(single_name);
+          }
+        }
+      }
+
+      // End position of the initializer is after the assignment expression.
+      initializer_position = scanner()->location().end_pos;
+    } else {
+      if ((parsing_result->descriptor.mode == CONST || is_pattern) &&
+          !is_for_iteration_variable) {
+        ParserTraits::ReportMessageAt(
+            Scanner::Location(decl_pos, scanner()->location().end_pos),
+            MessageTemplate::kDeclarationMissingInitializer,
+            is_pattern ? "destructuring" : "const");
+        *ok = false;
+        return;
+      }
+      // End position of the initializer is after the variable.
+      initializer_position = position();
+    }
+
+    // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
+    if (value == NULL && parsing_result->descriptor.needs_init) {
+      value = GetLiteralUndefined(position());
+    }
+
+    parsing_result->declarations.Add(DeclarationParsingResult::Declaration(
+        pattern, initializer_position, value));
+    first_declaration = false;
+  } while (peek() == Token::COMMA);
+
+  parsing_result->bindings_loc =
+      Scanner::Location(bindings_start, scanner()->location().end_pos);
+}
+
+
+static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
+                          const AstRawString* label) {
+  DCHECK(label != NULL);
+  if (labels != NULL) {
+    for (int i = labels->length(); i-- > 0; ) {
+      if (labels->at(i) == label) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+
+Statement* Parser::ParseExpressionOrLabelledStatement(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
+  // ExpressionStatement | LabelledStatement ::
+  //   Expression ';'
+  //   Identifier ':' Statement
+  //
+  // ExpressionStatement[Yield] :
+  //   [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ;
+
+  int pos = peek_position();
+
+  switch (peek()) {
+    case Token::FUNCTION:
+    case Token::LBRACE:
+      UNREACHABLE();  // Always handled by the callers.
+    case Token::CLASS:
+      ReportUnexpectedToken(Next());
+      *ok = false;
+      return nullptr;
+
+    case Token::THIS:
+      if (!FLAG_strong_this) break;
+      // Fall through.
+    case Token::SUPER:
+      if (is_strong(language_mode()) &&
+          IsClassConstructor(function_state_->kind())) {
+        bool is_this = peek() == Token::THIS;
+        Expression* expr;
+        ExpressionClassifier classifier;
+        if (is_this) {
+          expr = ParseStrongInitializationExpression(&classifier, CHECK_OK);
+        } else {
+          expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK);
+        }
+        expr = ParserTraits::RewriteNonPattern(expr, &classifier, CHECK_OK);
+        switch (peek()) {
+          case Token::SEMICOLON:
+            Consume(Token::SEMICOLON);
+            break;
+          case Token::RBRACE:
+          case Token::EOS:
+            break;
+          default:
+            if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
+              ReportMessageAt(function_state_->this_location(),
+                              is_this
+                                  ? MessageTemplate::kStrongConstructorThis
+                                  : MessageTemplate::kStrongConstructorSuper);
+              *ok = false;
+              return nullptr;
+            }
+        }
+        return factory()->NewExpressionStatement(expr, pos);
+      }
+      break;
+
+    default:
+      break;
+  }
+
+  bool starts_with_idenfifier = peek_any_identifier();
+  Expression* expr = ParseExpression(true, CHECK_OK);
+  if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
+      expr->AsVariableProxy() != NULL &&
+      !expr->AsVariableProxy()->is_this()) {
+    // Expression is a single identifier, and not, e.g., a parenthesized
+    // identifier.
+    VariableProxy* var = expr->AsVariableProxy();
+    const AstRawString* label = var->raw_name();
+    // TODO(1240780): We don't check for redeclaration of labels
+    // during preparsing since keeping track of the set of active
+    // labels requires nontrivial changes to the way scopes are
+    // structured.  However, these are probably changes we want to
+    // make later anyway so we should go back and fix this then.
+    if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
+      ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label);
+      *ok = false;
+      return NULL;
+    }
+    if (labels == NULL) {
+      labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
+    }
+    labels->Add(label, zone());
+    // Remove the "ghost" variable that turned out to be a label
+    // from the top scope. This way, we don't try to resolve it
+    // during the scope processing.
+    scope_->RemoveUnresolved(var);
+    Expect(Token::COLON, CHECK_OK);
+    return ParseStatement(labels, ok);
+  }
+
+  // If we have an extension, we allow a native function declaration.
+  // A native function declaration starts with "native function" with
+  // no line-terminator between the two words.
+  if (extension_ != NULL && peek() == Token::FUNCTION &&
+      !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
+      expr->AsVariableProxy() != NULL &&
+      expr->AsVariableProxy()->raw_name() ==
+          ast_value_factory()->native_string() &&
+      !scanner()->literal_contains_escapes()) {
+    return ParseNativeDeclaration(ok);
+  }
+
+  // Parsed expression statement, followed by semicolon.
+  // Detect attempts at 'let' declarations in sloppy mode.
+  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
+      expr->AsVariableProxy() != NULL &&
+      expr->AsVariableProxy()->raw_name() ==
+          ast_value_factory()->let_string()) {
+    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
+    *ok = false;
+    return NULL;
+  }
+  ExpectSemicolon(CHECK_OK);
+  return factory()->NewExpressionStatement(expr, pos);
+}
+
+
+IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
+                                      bool* ok) {
+  // IfStatement ::
+  //   'if' '(' Expression ')' Statement ('else' Statement)?
+
+  int pos = peek_position();
+  Expect(Token::IF, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* condition = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+  Statement* then_statement = ParseSubStatement(labels, CHECK_OK);
+  Statement* else_statement = NULL;
+  if (peek() == Token::ELSE) {
+    Next();
+    else_statement = ParseSubStatement(labels, CHECK_OK);
+  } else {
+    else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
+  }
+  return factory()->NewIfStatement(
+      condition, then_statement, else_statement, pos);
+}
+
+
+Statement* Parser::ParseContinueStatement(bool* ok) {
+  // ContinueStatement ::
+  //   'continue' Identifier? ';'
+
+  int pos = peek_position();
+  Expect(Token::CONTINUE, CHECK_OK);
+  const AstRawString* label = NULL;
+  Token::Value tok = peek();
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
+      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
+    // ECMA allows "eval" or "arguments" as labels even in strict mode.
+    label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+  }
+  IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
+  if (target == NULL) {
+    // Illegal continue statement.
+    MessageTemplate::Template message = MessageTemplate::kIllegalContinue;
+    if (label != NULL) {
+      message = MessageTemplate::kUnknownLabel;
+    }
+    ParserTraits::ReportMessage(message, label);
+    *ok = false;
+    return NULL;
+  }
+  ExpectSemicolon(CHECK_OK);
+  return factory()->NewContinueStatement(target, pos);
+}
+
+
+Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
+                                       bool* ok) {
+  // BreakStatement ::
+  //   'break' Identifier? ';'
+
+  int pos = peek_position();
+  Expect(Token::BREAK, CHECK_OK);
+  const AstRawString* label = NULL;
+  Token::Value tok = peek();
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
+      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
+    // ECMA allows "eval" or "arguments" as labels even in strict mode.
+    label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+  }
+  // Parse labeled break statements that target themselves into
+  // empty statements, e.g. 'l1: l2: l3: break l2;'
+  if (label != NULL && ContainsLabel(labels, label)) {
+    ExpectSemicolon(CHECK_OK);
+    return factory()->NewEmptyStatement(pos);
+  }
+  BreakableStatement* target = NULL;
+  target = LookupBreakTarget(label, CHECK_OK);
+  if (target == NULL) {
+    // Illegal break statement.
+    MessageTemplate::Template message = MessageTemplate::kIllegalBreak;
+    if (label != NULL) {
+      message = MessageTemplate::kUnknownLabel;
+    }
+    ParserTraits::ReportMessage(message, label);
+    *ok = false;
+    return NULL;
+  }
+  ExpectSemicolon(CHECK_OK);
+  return factory()->NewBreakStatement(target, pos);
+}
+
+
+Statement* Parser::ParseReturnStatement(bool* ok) {
+  // ReturnStatement ::
+  //   'return' Expression? ';'
+
+  // Consume the return token. It is necessary to do that before
+  // reporting any errors on it, because of the way errors are
+  // reported (underlining).
+  Expect(Token::RETURN, CHECK_OK);
+  Scanner::Location loc = scanner()->location();
+  function_state_->set_return_location(loc);
+
+  Token::Value tok = peek();
+  Statement* result;
+  Expression* return_value;
+  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
+      tok == Token::SEMICOLON ||
+      tok == Token::RBRACE ||
+      tok == Token::EOS) {
+    if (IsSubclassConstructor(function_state_->kind())) {
+      return_value = ThisExpression(scope_, factory(), loc.beg_pos);
+    } else {
+      return_value = GetLiteralUndefined(position());
+    }
+  } else {
+    if (is_strong(language_mode()) &&
+        IsClassConstructor(function_state_->kind())) {
+      int pos = peek_position();
+      ReportMessageAt(Scanner::Location(pos, pos + 1),
+                      MessageTemplate::kStrongConstructorReturnValue);
+      *ok = false;
+      return NULL;
+    }
+
+    int pos = peek_position();
+    return_value = ParseExpression(true, CHECK_OK);
+
+    if (IsSubclassConstructor(function_state_->kind())) {
+      // For subclass constructors we need to return this in case of undefined
+      // and throw an exception in case of a non object.
+      //
+      //   return expr;
+      //
+      // Is rewritten as:
+      //
+      //   return (temp = expr) === undefined ? this :
+      //       %_IsJSReceiver(temp) ? temp : throw new TypeError(...);
+      Variable* temp = scope_->NewTemporary(
+          ast_value_factory()->empty_string());
+      Assignment* assign = factory()->NewAssignment(
+          Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
+
+      Expression* throw_expression =
+          NewThrowTypeError(MessageTemplate::kDerivedConstructorReturn,
+                            ast_value_factory()->empty_string(), pos);
+
+      // %_IsJSReceiver(temp)
+      ZoneList<Expression*>* is_spec_object_args =
+          new (zone()) ZoneList<Expression*>(1, zone());
+      is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
+      Expression* is_spec_object_call = factory()->NewCallRuntime(
+          Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
+
+      // %_IsJSReceiver(temp) ? temp : throw_expression
+      Expression* is_object_conditional = factory()->NewConditional(
+          is_spec_object_call, factory()->NewVariableProxy(temp),
+          throw_expression, pos);
+
+      // temp === undefined
+      Expression* is_undefined = factory()->NewCompareOperation(
+          Token::EQ_STRICT, assign,
+          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos);
+
+      // is_undefined ? this : is_object_conditional
+      return_value = factory()->NewConditional(
+          is_undefined, ThisExpression(scope_, factory(), pos),
+          is_object_conditional, pos);
+    }
+
+    return_value->MarkTail();
+  }
+  ExpectSemicolon(CHECK_OK);
+
+  if (is_generator()) {
+    Expression* generator = factory()->NewVariableProxy(
+        function_state_->generator_object_variable());
+    Expression* yield = factory()->NewYield(
+        generator, return_value, Yield::kFinal, loc.beg_pos);
+    result = factory()->NewExpressionStatement(yield, loc.beg_pos);
+  } else {
+    result = factory()->NewReturnStatement(return_value, loc.beg_pos);
+  }
+
+  Scope* decl_scope = scope_->DeclarationScope();
+  if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
+    ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
+    *ok = false;
+    return NULL;
+  }
+  return result;
+}
+
+
+Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
+                                      bool* ok) {
+  // WithStatement ::
+  //   'with' '(' Expression ')' Statement
+
+  Expect(Token::WITH, CHECK_OK);
+  int pos = position();
+
+  if (is_strict(language_mode())) {
+    ReportMessage(MessageTemplate::kStrictWith);
+    *ok = false;
+    return NULL;
+  }
+
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* expr = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  scope_->DeclarationScope()->RecordWithStatement();
+  Scope* with_scope = NewScope(scope_, WITH_SCOPE);
+  Block* body;
+  { BlockState block_state(&scope_, with_scope);
+    with_scope->set_start_position(scanner()->peek_location().beg_pos);
+
+    // The body of the with statement must be enclosed in an additional
+    // lexical scope in case the body is a FunctionDeclaration.
+    body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
+    Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
+    block_scope->set_start_position(scanner()->location().beg_pos);
+    {
+      BlockState block_state(&scope_, block_scope);
+      Target target(&this->target_stack_, body);
+      Statement* stmt = ParseSubStatement(labels, CHECK_OK);
+      body->statements()->Add(stmt, zone());
+      block_scope->set_end_position(scanner()->location().end_pos);
+      block_scope = block_scope->FinalizeBlockScope();
+      body->set_scope(block_scope);
+    }
+
+    with_scope->set_end_position(scanner()->location().end_pos);
+  }
+  return factory()->NewWithStatement(with_scope, expr, body, pos);
+}
+
+
+CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
+  // CaseClause ::
+  //   'case' Expression ':' StatementList
+  //   'default' ':' StatementList
+
+  Expression* label = NULL;  // NULL expression indicates default case
+  if (peek() == Token::CASE) {
+    Expect(Token::CASE, CHECK_OK);
+    label = ParseExpression(true, CHECK_OK);
+  } else {
+    Expect(Token::DEFAULT, CHECK_OK);
+    if (*default_seen_ptr) {
+      ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
+      *ok = false;
+      return NULL;
+    }
+    *default_seen_ptr = true;
+  }
+  Expect(Token::COLON, CHECK_OK);
+  int pos = position();
+  ZoneList<Statement*>* statements =
+      new(zone()) ZoneList<Statement*>(5, zone());
+  Statement* stat = NULL;
+  while (peek() != Token::CASE &&
+         peek() != Token::DEFAULT &&
+         peek() != Token::RBRACE) {
+    stat = ParseStatementListItem(CHECK_OK);
+    statements->Add(stat, zone());
+  }
+  if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() &&
+      peek() != Token::RBRACE) {
+    ReportMessageAt(scanner()->location(),
+                    MessageTemplate::kStrongSwitchFallthrough);
+    *ok = false;
+    return NULL;
+  }
+  return factory()->NewCaseClause(label, statements, pos);
+}
+
+
+Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
+                                        bool* ok) {
+  // SwitchStatement ::
+  //   'switch' '(' Expression ')' '{' CaseClause* '}'
+  // In order to get the CaseClauses to execute in their own lexical scope,
+  // but without requiring downstream code to have special scope handling
+  // code for switch statements, desugar into blocks as follows:
+  // {  // To group the statements--harmless to evaluate Expression in scope
+  //   .tag_variable = Expression;
+  //   {  // To give CaseClauses a scope
+  //     switch (.tag_variable) { CaseClause* }
+  //   }
+  // }
+
+  Block* switch_block =
+      factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
+  int switch_pos = peek_position();
+
+  Expect(Token::SWITCH, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* tag = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  Variable* tag_variable =
+      scope_->NewTemporary(ast_value_factory()->dot_switch_tag_string());
+  Assignment* tag_assign = factory()->NewAssignment(
+      Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag,
+      tag->position());
+  Statement* tag_statement =
+      factory()->NewExpressionStatement(tag_assign, RelocInfo::kNoPosition);
+  switch_block->statements()->Add(tag_statement, zone());
+
+  // make statement: undefined;
+  // This is needed so the tag isn't returned as the value, in case the switch
+  // statements don't have a value.
+  switch_block->statements()->Add(
+      factory()->NewExpressionStatement(
+          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition),
+      zone());
+
+  Block* cases_block =
+      factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
+  Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE);
+  cases_scope->SetNonlinear();
+
+  SwitchStatement* switch_statement =
+      factory()->NewSwitchStatement(labels, switch_pos);
+
+  cases_scope->set_start_position(scanner()->location().beg_pos);
+  {
+    BlockState cases_block_state(&scope_, cases_scope);
+    Target target(&this->target_stack_, switch_statement);
+
+    Expression* tag_read = factory()->NewVariableProxy(tag_variable);
+
+    bool default_seen = false;
+    ZoneList<CaseClause*>* cases =
+        new (zone()) ZoneList<CaseClause*>(4, zone());
+    Expect(Token::LBRACE, CHECK_OK);
+    while (peek() != Token::RBRACE) {
+      CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
+      cases->Add(clause, zone());
+    }
+    switch_statement->Initialize(tag_read, cases);
+    cases_block->statements()->Add(switch_statement, zone());
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+
+  cases_scope->set_end_position(scanner()->location().end_pos);
+  cases_scope = cases_scope->FinalizeBlockScope();
+  cases_block->set_scope(cases_scope);
+
+  switch_block->statements()->Add(cases_block, zone());
+
+  return switch_block;
+}
+
+
+Statement* Parser::ParseThrowStatement(bool* ok) {
+  // ThrowStatement ::
+  //   'throw' Expression ';'
+
+  Expect(Token::THROW, CHECK_OK);
+  int pos = position();
+  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
+    ReportMessage(MessageTemplate::kNewlineAfterThrow);
+    *ok = false;
+    return NULL;
+  }
+  Expression* exception = ParseExpression(true, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+
+  return factory()->NewExpressionStatement(
+      factory()->NewThrow(exception, pos), pos);
+}
+
+
+TryStatement* Parser::ParseTryStatement(bool* ok) {
+  // TryStatement ::
+  //   'try' Block Catch
+  //   'try' Block Finally
+  //   'try' Block Catch Finally
+  //
+  // Catch ::
+  //   'catch' '(' Identifier ')' Block
+  //
+  // Finally ::
+  //   'finally' Block
+
+  Expect(Token::TRY, CHECK_OK);
+  int pos = position();
+
+  Block* try_block = ParseBlock(NULL, CHECK_OK);
+
+  Token::Value tok = peek();
+  if (tok != Token::CATCH && tok != Token::FINALLY) {
+    ReportMessage(MessageTemplate::kNoCatchOrFinally);
+    *ok = false;
+    return NULL;
+  }
+
+  Scope* catch_scope = NULL;
+  Variable* catch_variable = NULL;
+  Block* catch_block = NULL;
+  if (tok == Token::CATCH) {
+    Consume(Token::CATCH);
+
+    Expect(Token::LPAREN, CHECK_OK);
+    catch_scope = NewScope(scope_, CATCH_SCOPE);
+    catch_scope->set_start_position(scanner()->location().beg_pos);
+
+    ExpressionClassifier pattern_classifier;
+    Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
+    ValidateBindingPattern(&pattern_classifier, CHECK_OK);
+
+    const AstRawString* name = ast_value_factory()->dot_catch_string();
+    bool is_simple = pattern->IsVariableProxy();
+    if (is_simple) {
+      auto proxy = pattern->AsVariableProxy();
+      scope_->RemoveUnresolved(proxy);
+      name = proxy->raw_name();
+    }
+
+    catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
+                                               Variable::NORMAL);
+
+    Expect(Token::RPAREN, CHECK_OK);
+
+    {
+      BlockState block_state(&scope_, catch_scope);
+
+      // TODO(adamk): Make a version of ParseBlock that takes a scope and
+      // a block.
+      catch_block =
+          factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
+      Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
+
+      block_scope->set_start_position(scanner()->location().beg_pos);
+      {
+        BlockState block_state(&scope_, block_scope);
+        Target target(&this->target_stack_, catch_block);
+
+        if (!is_simple) {
+          DeclarationDescriptor descriptor;
+          descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
+          descriptor.parser = this;
+          descriptor.scope = scope_;
+          descriptor.hoist_scope = nullptr;
+          descriptor.mode = LET;
+          descriptor.needs_init = true;
+          descriptor.declaration_pos = pattern->position();
+          descriptor.initialization_pos = pattern->position();
+
+          DeclarationParsingResult::Declaration decl(
+              pattern, pattern->position(),
+              factory()->NewVariableProxy(catch_variable));
+
+          PatternRewriter::DeclareAndInitializeVariables(
+              catch_block, &descriptor, &decl, nullptr, CHECK_OK);
+        }
+
+        Expect(Token::LBRACE, CHECK_OK);
+        while (peek() != Token::RBRACE) {
+          Statement* stat = ParseStatementListItem(CHECK_OK);
+          if (stat && !stat->IsEmpty()) {
+            catch_block->statements()->Add(stat, zone());
+          }
+        }
+        Consume(Token::RBRACE);
+      }
+      block_scope->set_end_position(scanner()->location().end_pos);
+      block_scope = block_scope->FinalizeBlockScope();
+      catch_block->set_scope(block_scope);
+    }
+
+    catch_scope->set_end_position(scanner()->location().end_pos);
+    tok = peek();
+  }
+
+  Block* finally_block = NULL;
+  DCHECK(tok == Token::FINALLY || catch_block != NULL);
+  if (tok == Token::FINALLY) {
+    Consume(Token::FINALLY);
+    finally_block = ParseBlock(NULL, CHECK_OK);
+  }
+
+  // Simplify the AST nodes by converting:
+  //   'try B0 catch B1 finally B2'
+  // to:
+  //   'try { try B0 catch B1 } finally B2'
+
+  if (catch_block != NULL && finally_block != NULL) {
+    // If we have both, create an inner try/catch.
+    DCHECK(catch_scope != NULL && catch_variable != NULL);
+    TryCatchStatement* statement =
+        factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
+                                        catch_block, RelocInfo::kNoPosition);
+    try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
+    try_block->statements()->Add(statement, zone());
+    catch_block = NULL;  // Clear to indicate it's been handled.
+  }
+
+  TryStatement* result = NULL;
+  if (catch_block != NULL) {
+    DCHECK(finally_block == NULL);
+    DCHECK(catch_scope != NULL && catch_variable != NULL);
+    result = factory()->NewTryCatchStatement(try_block, catch_scope,
+                                             catch_variable, catch_block, pos);
+  } else {
+    DCHECK(finally_block != NULL);
+    result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
+  }
+
+  return result;
+}
+
+
+DoWhileStatement* Parser::ParseDoWhileStatement(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
+  // DoStatement ::
+  //   'do' Statement 'while' '(' Expression ')' ';'
+
+  DoWhileStatement* loop =
+      factory()->NewDoWhileStatement(labels, peek_position());
+  Target target(&this->target_stack_, loop);
+
+  Expect(Token::DO, CHECK_OK);
+  Statement* body = ParseSubStatement(NULL, CHECK_OK);
+  Expect(Token::WHILE, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+
+  Expression* cond = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  // Allow do-statements to be terminated with and without
+  // semi-colons. This allows code such as 'do;while(0)return' to
+  // parse, which would not be the case if we had used the
+  // ExpectSemicolon() functionality here.
+  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
+
+  if (loop != NULL) loop->Initialize(cond, body);
+  return loop;
+}
+
+
+WhileStatement* Parser::ParseWhileStatement(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
+  // WhileStatement ::
+  //   'while' '(' Expression ')' Statement
+
+  WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
+  Target target(&this->target_stack_, loop);
+
+  Expect(Token::WHILE, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* cond = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+  Statement* body = ParseSubStatement(NULL, CHECK_OK);
+
+  if (loop != NULL) loop->Initialize(cond, body);
+  return loop;
+}
+
+
+// !%_IsJSReceiver(result = iterator.next()) &&
+//     %ThrowIteratorResultNotAnObject(result)
+Expression* Parser::BuildIteratorNextResult(Expression* iterator,
+                                            Variable* result, int pos) {
+  Expression* next_literal = factory()->NewStringLiteral(
+      ast_value_factory()->next_string(), RelocInfo::kNoPosition);
+  Expression* next_property =
+      factory()->NewProperty(iterator, next_literal, RelocInfo::kNoPosition);
+  ZoneList<Expression*>* next_arguments =
+      new (zone()) ZoneList<Expression*>(0, zone());
+  Expression* next_call =
+      factory()->NewCall(next_property, next_arguments, pos);
+  Expression* result_proxy = factory()->NewVariableProxy(result);
+  Expression* left =
+      factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);
+
+  // %_IsJSReceiver(...)
+  ZoneList<Expression*>* is_spec_object_args =
+      new (zone()) ZoneList<Expression*>(1, zone());
+  is_spec_object_args->Add(left, zone());
+  Expression* is_spec_object_call = factory()->NewCallRuntime(
+      Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
+
+  // %ThrowIteratorResultNotAnObject(result)
+  Expression* result_proxy_again = factory()->NewVariableProxy(result);
+  ZoneList<Expression*>* throw_arguments =
+      new (zone()) ZoneList<Expression*>(1, zone());
+  throw_arguments->Add(result_proxy_again, zone());
+  Expression* throw_call = factory()->NewCallRuntime(
+      Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
+
+  return factory()->NewBinaryOperation(
+      Token::AND,
+      factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
+      throw_call, pos);
+}
+
+
+void Parser::InitializeForEachStatement(ForEachStatement* stmt,
+                                        Expression* each, Expression* subject,
+                                        Statement* body,
+                                        bool is_destructuring) {
+  DCHECK(!is_destructuring || allow_harmony_destructuring_assignment());
+  ForOfStatement* for_of = stmt->AsForOfStatement();
+
+  if (for_of != NULL) {
+    Variable* iterator = scope_->NewTemporary(
+        ast_value_factory()->dot_iterator_string());
+    Variable* result = scope_->NewTemporary(
+        ast_value_factory()->dot_result_string());
+
+    Expression* assign_iterator;
+    Expression* next_result;
+    Expression* result_done;
+    Expression* assign_each;
+
+    // iterator = subject[Symbol.iterator]()
+    // Hackily disambiguate o from o.next and o [Symbol.iterator]().
+    // TODO(verwaest): Come up with a better solution.
+    assign_iterator = factory()->NewAssignment(
+        Token::ASSIGN, factory()->NewVariableProxy(iterator),
+        GetIterator(subject, factory(), subject->position() - 2),
+        subject->position());
+
+    // !%_IsJSReceiver(result = iterator.next()) &&
+    //     %ThrowIteratorResultNotAnObject(result)
+    {
+      // result = iterator.next()
+      Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
+      // Hackily disambiguate o from o.next and o [Symbol.iterator]().
+      // TODO(verwaest): Come up with a better solution.
+      next_result = BuildIteratorNextResult(iterator_proxy, result,
+                                            subject->position() - 1);
+    }
+
+    // result.done
+    {
+      Expression* done_literal = factory()->NewStringLiteral(
+          ast_value_factory()->done_string(), RelocInfo::kNoPosition);
+      Expression* result_proxy = factory()->NewVariableProxy(result);
+      result_done = factory()->NewProperty(
+          result_proxy, done_literal, RelocInfo::kNoPosition);
+    }
+
+    // each = result.value
+    {
+      Expression* value_literal = factory()->NewStringLiteral(
+          ast_value_factory()->value_string(), RelocInfo::kNoPosition);
+      Expression* result_proxy = factory()->NewVariableProxy(result);
+      Expression* result_value = factory()->NewProperty(
+          result_proxy, value_literal, RelocInfo::kNoPosition);
+      assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
+                                             RelocInfo::kNoPosition);
+      if (is_destructuring) {
+        assign_each = PatternRewriter::RewriteDestructuringAssignment(
+            this, assign_each->AsAssignment(), scope_);
+      }
+    }
+
+    for_of->Initialize(each, subject, body,
+                       assign_iterator,
+                       next_result,
+                       result_done,
+                       assign_each);
+  } else {
+    if (is_destructuring) {
+      Variable* temp =
+          scope_->NewTemporary(ast_value_factory()->empty_string());
+      VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
+      Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
+          this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
+                                         RelocInfo::kNoPosition),
+          scope_);
+      auto block =
+          factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition);
+      block->statements()->Add(factory()->NewExpressionStatement(
+                                   assign_each, RelocInfo::kNoPosition),
+                               zone());
+      block->statements()->Add(body, zone());
+      body = block;
+      each = factory()->NewVariableProxy(temp);
+    }
+    stmt->Initialize(each, subject, body);
+  }
+}
+
+
+Statement* Parser::DesugarLexicalBindingsInForStatement(
+    Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names,
+    ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+    Statement* body, bool* ok) {
+  // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
+  // copied into a new environment.  Moreover, the "next" statement must be
+  // evaluated not in the environment of the just completed iteration but in
+  // that of the upcoming one.  We achieve this with the following desugaring.
+  // Extra care is needed to preserve the completion value of the original loop.
+  //
+  // We are given a for statement of the form
+  //
+  //  labels: for (let/const x = i; cond; next) body
+  //
+  // and rewrite it as follows.  Here we write {{ ... }} for init-blocks, ie.,
+  // blocks whose ignore_completion_value_ flag is set.
+  //
+  //  {
+  //    let/const x = i;
+  //    temp_x = x;
+  //    first = 1;
+  //    undefined;
+  //    outer: for (;;) {
+  //      let/const x = temp_x;
+  //      {{ if (first == 1) {
+  //           first = 0;
+  //         } else {
+  //           next;
+  //         }
+  //         flag = 1;
+  //         if (!cond) break;
+  //      }}
+  //      labels: for (; flag == 1; flag = 0, temp_x = x) {
+  //        body
+  //      }
+  //      {{ if (flag == 1)  // Body used break.
+  //           break;
+  //      }}
+  //    }
+  //  }
+
+  DCHECK(names->length() > 0);
+  Scope* for_scope = scope_;
+  ZoneList<Variable*> temps(names->length(), zone());
+
+  Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
+                                           RelocInfo::kNoPosition);
+
+  // Add statement: let/const x = i.
+  outer_block->statements()->Add(init, zone());
+
+  const AstRawString* temp_name = ast_value_factory()->dot_for_string();
+
+  // For each lexical variable x:
+  //   make statement: temp_x = x.
+  for (int i = 0; i < names->length(); i++) {
+    VariableProxy* proxy = NewUnresolved(names->at(i), LET);
+    Variable* temp = scope_->NewTemporary(temp_name);
+    VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
+    Assignment* assignment = factory()->NewAssignment(
+        Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
+    Statement* assignment_statement = factory()->NewExpressionStatement(
+        assignment, RelocInfo::kNoPosition);
+    outer_block->statements()->Add(assignment_statement, zone());
+    temps.Add(temp, zone());
+  }
+
+  Variable* first = NULL;
+  // Make statement: first = 1.
+  if (next) {
+    first = scope_->NewTemporary(temp_name);
+    VariableProxy* first_proxy = factory()->NewVariableProxy(first);
+    Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
+    Assignment* assignment = factory()->NewAssignment(
+        Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition);
+    Statement* assignment_statement =
+        factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
+    outer_block->statements()->Add(assignment_statement, zone());
+  }
+
+  // make statement: undefined;
+  outer_block->statements()->Add(
+      factory()->NewExpressionStatement(
+          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition),
+      zone());
+
+  // Make statement: outer: for (;;)
+  // Note that we don't actually create the label, or set this loop up as an
+  // explicit break target, instead handing it directly to those nodes that
+  // need to know about it. This should be safe because we don't run any code
+  // in this function that looks up break targets.
+  ForStatement* outer_loop =
+      factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
+  outer_block->statements()->Add(outer_loop, zone());
+
+  outer_block->set_scope(for_scope);
+  scope_ = inner_scope;
+
+  Block* inner_block =
+      factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
+  Block* ignore_completion_block = factory()->NewBlock(
+      NULL, names->length() + 3, true, RelocInfo::kNoPosition);
+  ZoneList<Variable*> inner_vars(names->length(), zone());
+  // For each let variable x:
+  //    make statement: let/const x = temp_x.
+  VariableMode mode = is_const ? CONST : LET;
+  for (int i = 0; i < names->length(); i++) {
+    VariableProxy* proxy = NewUnresolved(names->at(i), mode);
+    Declaration* declaration = factory()->NewVariableDeclaration(
+        proxy, mode, scope_, RelocInfo::kNoPosition);
+    Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
+    inner_vars.Add(declaration->proxy()->var(), zone());
+    VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
+    Assignment* assignment = factory()->NewAssignment(
+        Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition);
+    Statement* assignment_statement =
+        factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
+    DCHECK(init->position() != RelocInfo::kNoPosition);
+    proxy->var()->set_initializer_position(init->position());
+    ignore_completion_block->statements()->Add(assignment_statement, zone());
+  }
+
+  // Make statement: if (first == 1) { first = 0; } else { next; }
+  if (next) {
+    DCHECK(first);
+    Expression* compare = NULL;
+    // Make compare expression: first == 1.
+    {
+      Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
+      VariableProxy* first_proxy = factory()->NewVariableProxy(first);
+      compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
+                                               RelocInfo::kNoPosition);
+    }
+    Statement* clear_first = NULL;
+    // Make statement: first = 0.
+    {
+      VariableProxy* first_proxy = factory()->NewVariableProxy(first);
+      Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
+      Assignment* assignment = factory()->NewAssignment(
+          Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition);
+      clear_first =
+          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
+    }
+    Statement* clear_first_or_next = factory()->NewIfStatement(
+        compare, clear_first, next, RelocInfo::kNoPosition);
+    ignore_completion_block->statements()->Add(clear_first_or_next, zone());
+  }
+
+  Variable* flag = scope_->NewTemporary(temp_name);
+  // Make statement: flag = 1.
+  {
+    VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
+    Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
+    Assignment* assignment = factory()->NewAssignment(
+        Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
+    Statement* assignment_statement =
+        factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
+    ignore_completion_block->statements()->Add(assignment_statement, zone());
+  }
+
+  // Make statement: if (!cond) break.
+  if (cond) {
+    Statement* stop =
+        factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
+    Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
+    ignore_completion_block->statements()->Add(
+        factory()->NewIfStatement(cond, noop, stop, cond->position()), zone());
+  }
+
+  inner_block->statements()->Add(ignore_completion_block, zone());
+  // Make cond expression for main loop: flag == 1.
+  Expression* flag_cond = NULL;
+  {
+    Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
+    VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
+    flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
+                                               RelocInfo::kNoPosition);
+  }
+
+  // Create chain of expressions "flag = 0, temp_x = x, ..."
+  Statement* compound_next_statement = NULL;
+  {
+    Expression* compound_next = NULL;
+    // Make expression: flag = 0.
+    {
+      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
+      Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
+      compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy,
+                                               const0, RelocInfo::kNoPosition);
+    }
+
+    // Make the comma-separated list of temp_x = x assignments.
+    int inner_var_proxy_pos = scanner()->location().beg_pos;
+    for (int i = 0; i < names->length(); i++) {
+      VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
+      VariableProxy* proxy =
+          factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
+      Assignment* assignment = factory()->NewAssignment(
+          Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
+      compound_next = factory()->NewBinaryOperation(
+          Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
+    }
+
+    compound_next_statement = factory()->NewExpressionStatement(
+        compound_next, RelocInfo::kNoPosition);
+  }
+
+  // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
+  // Note that we re-use the original loop node, which retains its labels
+  // and ensures that any break or continue statements in body point to
+  // the right place.
+  loop->Initialize(NULL, flag_cond, compound_next_statement, body);
+  inner_block->statements()->Add(loop, zone());
+
+  // Make statement: {{if (flag == 1) break;}}
+  {
+    Expression* compare = NULL;
+    // Make compare expresion: flag == 1.
+    {
+      Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
+      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
+      compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
+                                               RelocInfo::kNoPosition);
+    }
+    Statement* stop =
+        factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
+    Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
+    Statement* if_flag_break =
+        factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition);
+    Block* ignore_completion_block =
+        factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
+    ignore_completion_block->statements()->Add(if_flag_break, zone());
+    inner_block->statements()->Add(ignore_completion_block, zone());
+  }
+
+  inner_scope->set_end_position(scanner()->location().end_pos);
+  inner_block->set_scope(inner_scope);
+  scope_ = for_scope;
+
+  outer_loop->Initialize(NULL, NULL, NULL, inner_block);
+  return outer_block;
+}
+
+
+Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
+                                     bool* ok) {
+  // ForStatement ::
+  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
+
+  int stmt_pos = peek_position();
+  bool is_const = false;
+  Statement* init = NULL;
+  ZoneList<const AstRawString*> lexical_bindings(1, zone());
+
+  // Create an in-between scope for let-bound iteration variables.
+  Scope* saved_scope = scope_;
+  Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
+  scope_ = for_scope;
+  Expect(Token::FOR, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  for_scope->set_start_position(scanner()->location().beg_pos);
+  bool is_let_identifier_expression = false;
+  DeclarationParsingResult parsing_result;
+  if (peek() != Token::SEMICOLON) {
+    if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
+        (peek() == Token::LET && IsNextLetKeyword())) {
+      ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
+      is_const = parsing_result.descriptor.mode == CONST;
+
+      int num_decl = parsing_result.declarations.length();
+      bool accept_IN = num_decl >= 1;
+      ForEachStatement::VisitMode mode;
+      int each_beg_pos = scanner()->location().beg_pos;
+      int each_end_pos = scanner()->location().end_pos;
+
+      if (accept_IN && CheckInOrOf(&mode, ok)) {
+        if (!*ok) return nullptr;
+        if (num_decl != 1) {
+          const char* loop_type =
+              mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
+          ParserTraits::ReportMessageAt(
+              parsing_result.bindings_loc,
+              MessageTemplate::kForInOfLoopMultiBindings, loop_type);
+          *ok = false;
+          return nullptr;
+        }
+        DeclarationParsingResult::Declaration& decl =
+            parsing_result.declarations[0];
+        if (parsing_result.first_initializer_loc.IsValid() &&
+            (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
+             IsLexicalVariableMode(parsing_result.descriptor.mode) ||
+             !decl.pattern->IsVariableProxy())) {
+          if (mode == ForEachStatement::ITERATE) {
+            ReportMessageAt(parsing_result.first_initializer_loc,
+                            MessageTemplate::kForOfLoopInitializer);
+          } else {
+            // TODO(caitp): This should be an error in sloppy mode too.
+            ReportMessageAt(parsing_result.first_initializer_loc,
+                            MessageTemplate::kForInLoopInitializer);
+          }
+          *ok = false;
+          return nullptr;
+        }
+
+        Block* init_block = nullptr;
+
+        // special case for legacy for (var/const x =.... in)
+        if (!IsLexicalVariableMode(parsing_result.descriptor.mode) &&
+            decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
+          const AstRawString* name =
+              decl.pattern->AsVariableProxy()->raw_name();
+          VariableProxy* single_var = scope_->NewUnresolved(
+              factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos);
+          init_block = factory()->NewBlock(
+              nullptr, 2, true, parsing_result.descriptor.declaration_pos);
+          init_block->statements()->Add(
+              factory()->NewExpressionStatement(
+                  factory()->NewAssignment(Token::ASSIGN, single_var,
+                                           decl.initializer,
+                                           RelocInfo::kNoPosition),
+                  RelocInfo::kNoPosition),
+              zone());
+        }
+
+        // Rewrite a for-in/of statement of the form
+        //
+        //   for (let/const/var x in/of e) b
+        //
+        // into
+        //
+        //   {
+        //     <let x' be a temporary variable>
+        //     for (x' in/of e) {
+        //       let/const/var x;
+        //       x = x';
+        //       b;
+        //     }
+        //     let x;  // for TDZ
+        //   }
+
+        Variable* temp = scope_->NewTemporary(
+            ast_value_factory()->dot_for_string());
+        ForEachStatement* loop =
+            factory()->NewForEachStatement(mode, labels, stmt_pos);
+        Target target(&this->target_stack_, loop);
+
+        Expression* enumerable = ParseExpression(true, CHECK_OK);
+
+        Expect(Token::RPAREN, CHECK_OK);
+
+        Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
+        body_scope->set_start_position(scanner()->location().beg_pos);
+        scope_ = body_scope;
+
+        Statement* body = ParseSubStatement(NULL, CHECK_OK);
+
+        Block* body_block =
+            factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
+
+        auto each_initialization_block =
+            factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
+        {
+          auto descriptor = parsing_result.descriptor;
+          descriptor.declaration_pos = RelocInfo::kNoPosition;
+          descriptor.initialization_pos = RelocInfo::kNoPosition;
+          decl.initializer = factory()->NewVariableProxy(temp);
+
+          PatternRewriter::DeclareAndInitializeVariables(
+              each_initialization_block, &descriptor, &decl,
+              IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
+                                                     : nullptr,
+              CHECK_OK);
+        }
+
+        body_block->statements()->Add(each_initialization_block, zone());
+        body_block->statements()->Add(body, zone());
+        VariableProxy* temp_proxy =
+            factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
+        InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
+                                   false);
+        scope_ = for_scope;
+        body_scope->set_end_position(scanner()->location().end_pos);
+        body_scope = body_scope->FinalizeBlockScope();
+        if (body_scope != nullptr) {
+          body_block->set_scope(body_scope);
+        }
+
+        // Create a TDZ for any lexically-bound names.
+        if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
+          DCHECK_NULL(init_block);
+
+          init_block =
+              factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
+
+          for (int i = 0; i < lexical_bindings.length(); ++i) {
+            // TODO(adamk): This needs to be some sort of special
+            // INTERNAL variable that's invisible to the debugger
+            // but visible to everything else.
+            VariableProxy* tdz_proxy = NewUnresolved(lexical_bindings[i], LET);
+            Declaration* tdz_decl = factory()->NewVariableDeclaration(
+                tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
+            Variable* tdz_var = Declare(tdz_decl, DeclarationDescriptor::NORMAL,
+                                        true, CHECK_OK);
+            tdz_var->set_initializer_position(position());
+          }
+        }
+
+        scope_ = saved_scope;
+        for_scope->set_end_position(scanner()->location().end_pos);
+        for_scope = for_scope->FinalizeBlockScope();
+        // Parsed for-in loop w/ variable declarations.
+        if (init_block != nullptr) {
+          init_block->statements()->Add(loop, zone());
+          if (for_scope != nullptr) {
+            init_block->set_scope(for_scope);
+          }
+          return init_block;
+        } else {
+          DCHECK_NULL(for_scope);
+          return loop;
+        }
+      } else {
+        init = parsing_result.BuildInitializationBlock(
+            IsLexicalVariableMode(parsing_result.descriptor.mode)
+                ? &lexical_bindings
+                : nullptr,
+            CHECK_OK);
+      }
+    } else {
+      int lhs_beg_pos = peek_position();
+      ExpressionClassifier classifier;
+      Expression* expression = ParseExpression(false, &classifier, CHECK_OK);
+      int lhs_end_pos = scanner()->location().end_pos;
+      ForEachStatement::VisitMode mode;
+      is_let_identifier_expression =
+          expression->IsVariableProxy() &&
+          expression->AsVariableProxy()->raw_name() ==
+              ast_value_factory()->let_string();
+
+      bool is_for_each = CheckInOrOf(&mode, ok);
+      if (!*ok) return nullptr;
+      bool is_destructuring =
+          is_for_each && allow_harmony_destructuring_assignment() &&
+          (expression->IsArrayLiteral() || expression->IsObjectLiteral());
+
+      if (is_destructuring) {
+        ValidateAssignmentPattern(&classifier, CHECK_OK);
+      } else {
+        expression =
+            ParserTraits::RewriteNonPattern(expression, &classifier, CHECK_OK);
+      }
+
+      if (is_for_each) {
+        if (!is_destructuring) {
+          expression = this->CheckAndRewriteReferenceExpression(
+              expression, lhs_beg_pos, lhs_end_pos,
+              MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
+        }
+
+        ForEachStatement* loop =
+            factory()->NewForEachStatement(mode, labels, stmt_pos);
+        Target target(&this->target_stack_, loop);
+
+        Expression* enumerable = ParseExpression(true, CHECK_OK);
+        Expect(Token::RPAREN, CHECK_OK);
+
+        // Make a block around the statement in case a lexical binding
+        // is introduced, e.g. by a FunctionDeclaration.
+        // This block must not use for_scope as its scope because if a
+        // lexical binding is introduced which overlaps with the for-in/of,
+        // expressions in head of the loop should actually have variables
+        // resolved in the outer scope.
+        Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE);
+        scope_ = body_scope;
+        Block* block =
+            factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
+        Statement* body = ParseSubStatement(NULL, CHECK_OK);
+        block->statements()->Add(body, zone());
+        InitializeForEachStatement(loop, expression, enumerable, block,
+                                   is_destructuring);
+        scope_ = saved_scope;
+        body_scope->set_end_position(scanner()->location().end_pos);
+        body_scope = body_scope->FinalizeBlockScope();
+        if (body_scope != nullptr) {
+          block->set_scope(body_scope);
+        }
+        for_scope->set_end_position(scanner()->location().end_pos);
+        for_scope = for_scope->FinalizeBlockScope();
+        DCHECK(for_scope == nullptr);
+        // Parsed for-in loop.
+        return loop;
+
+      } else {
+        init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
+      }
+    }
+  }
+
+  // Standard 'for' loop
+  ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
+  Target target(&this->target_stack_, loop);
+
+  // Parsed initializer at this point.
+  // Detect attempts at 'let' declarations in sloppy mode.
+  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
+      is_sloppy(language_mode()) && is_let_identifier_expression) {
+    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
+    *ok = false;
+    return NULL;
+  }
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  // If there are let bindings, then condition and the next statement of the
+  // for loop must be parsed in a new scope.
+  Scope* inner_scope = NULL;
+  if (lexical_bindings.length() > 0) {
+    inner_scope = NewScope(for_scope, BLOCK_SCOPE);
+    inner_scope->set_start_position(scanner()->location().beg_pos);
+    scope_ = inner_scope;
+  }
+
+  Expression* cond = NULL;
+  if (peek() != Token::SEMICOLON) {
+    cond = ParseExpression(true, CHECK_OK);
+  }
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  Statement* next = NULL;
+  if (peek() != Token::RPAREN) {
+    Expression* exp = ParseExpression(true, CHECK_OK);
+    next = factory()->NewExpressionStatement(exp, exp->position());
+  }
+  Expect(Token::RPAREN, CHECK_OK);
+
+  Statement* body = ParseSubStatement(NULL, CHECK_OK);
+
+  Statement* result = NULL;
+  if (lexical_bindings.length() > 0) {
+    scope_ = for_scope;
+    result = DesugarLexicalBindingsInForStatement(
+                 inner_scope, is_const, &lexical_bindings, loop, init, cond,
+                 next, body, CHECK_OK);
+    scope_ = saved_scope;
+    for_scope->set_end_position(scanner()->location().end_pos);
+  } else {
+    scope_ = saved_scope;
+    for_scope->set_end_position(scanner()->location().end_pos);
+    for_scope = for_scope->FinalizeBlockScope();
+    if (for_scope) {
+      // Rewrite a for statement of the form
+      //   for (const x = i; c; n) b
+      //
+      // into
+      //
+      //   {
+      //     const x = i;
+      //     for (; c; n) b
+      //   }
+      //
+      // or, desugar
+      //   for (; c; n) b
+      // into
+      //   {
+      //     for (; c; n) b
+      //   }
+      // just in case b introduces a lexical binding some other way, e.g., if b
+      // is a FunctionDeclaration.
+      Block* block =
+          factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
+      if (init != nullptr) {
+        block->statements()->Add(init, zone());
+      }
+      block->statements()->Add(loop, zone());
+      block->set_scope(for_scope);
+      loop->Initialize(NULL, cond, next, body);
+      result = block;
+    } else {
+      loop->Initialize(init, cond, next, body);
+      result = loop;
+    }
+  }
+  return result;
+}
+
+
+DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
+  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
+  // contexts this is used as a statement which invokes the debugger as i a
+  // break point is present.
+  // DebuggerStatement ::
+  //   'debugger' ';'
+
+  int pos = peek_position();
+  Expect(Token::DEBUGGER, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+  return factory()->NewDebuggerStatement(pos);
+}
+
+
+bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
+  if (expression->IsLiteral()) return true;
+  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
+  return lit != NULL && lit->is_simple();
+}
+
+
+Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
+                                              Expression* expression) {
+  Factory* factory = isolate->factory();
+  DCHECK(IsCompileTimeValue(expression));
+  Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
+  ObjectLiteral* object_literal = expression->AsObjectLiteral();
+  if (object_literal != NULL) {
+    DCHECK(object_literal->is_simple());
+    if (object_literal->fast_elements()) {
+      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
+    } else {
+      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
+    }
+    result->set(kElementsSlot, *object_literal->constant_properties());
+  } else {
+    ArrayLiteral* array_literal = expression->AsArrayLiteral();
+    DCHECK(array_literal != NULL && array_literal->is_simple());
+    result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
+    result->set(kElementsSlot, *array_literal->constant_elements());
+  }
+  return result;
+}
+
+
+CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
+    Handle<FixedArray> value) {
+  Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
+  return static_cast<LiteralType>(literal_type->value());
+}
+
+
+Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
+  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
+}
+
+
+void ParserTraits::ParseArrowFunctionFormalParameters(
+    ParserFormalParameters* parameters, Expression* expr,
+    const Scanner::Location& params_loc, bool* ok) {
+  if (parameters->Arity() >= Code::kMaxArguments) {
+    ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
+    *ok = false;
+    return;
+  }
+
+  // ArrowFunctionFormals ::
+  //    Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
+  //    Tail
+  // NonTailArrowFunctionFormals ::
+  //    Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
+  //    VariableProxy
+  // Tail ::
+  //    VariableProxy
+  //    Spread(VariableProxy)
+  //
+  // As we need to visit the parameters in left-to-right order, we recurse on
+  // the left-hand side of comma expressions.
+  //
+  if (expr->IsBinaryOperation()) {
+    BinaryOperation* binop = expr->AsBinaryOperation();
+    // The classifier has already run, so we know that the expression is a valid
+    // arrow function formals production.
+    DCHECK_EQ(binop->op(), Token::COMMA);
+    Expression* left = binop->left();
+    Expression* right = binop->right();
+    ParseArrowFunctionFormalParameters(parameters, left, params_loc, ok);
+    if (!*ok) return;
+    // LHS of comma expression should be unparenthesized.
+    expr = right;
+  }
+
+  // Only the right-most expression may be a rest parameter.
+  DCHECK(!parameters->has_rest);
+
+  bool is_rest = expr->IsSpread();
+  if (is_rest) {
+    expr = expr->AsSpread()->expression();
+    parameters->has_rest = true;
+  }
+  if (parameters->is_simple) {
+    parameters->is_simple = !is_rest && expr->IsVariableProxy();
+  }
+
+  Expression* initializer = nullptr;
+  if (expr->IsVariableProxy()) {
+    // When the formal parameter was originally seen, it was parsed as a
+    // VariableProxy and recorded as unresolved in the scope.  Here we undo that
+    // parse-time side-effect for parameters that are single-names (not
+    // patterns; for patterns that happens uniformly in
+    // PatternRewriter::VisitVariableProxy).
+    parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
+  } else if (expr->IsAssignment()) {
+    Assignment* assignment = expr->AsAssignment();
+    DCHECK(parser_->allow_harmony_default_parameters());
+    DCHECK(!assignment->is_compound());
+    initializer = assignment->value();
+    expr = assignment->target();
+
+    // TODO(adamk): Only call this if necessary.
+    RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
+                                     parser_->scope_, parameters->scope);
+  }
+
+  // TODO(adamk): params_loc.end_pos is not the correct initializer position,
+  // but it should be conservative enough to trigger hole checks for variables
+  // referenced in the initializer (if any).
+  AddFormalParameter(parameters, expr, initializer, params_loc.end_pos,
+                     is_rest);
+}
+
+
+DoExpression* Parser::ParseDoExpression(bool* ok) {
+  // AssignmentExpression ::
+  //     do '{' StatementList '}'
+  int pos = peek_position();
+
+  Expect(Token::DO, CHECK_OK);
+  Variable* result =
+      scope_->NewTemporary(ast_value_factory()->dot_result_string());
+  Block* block = ParseBlock(nullptr, false, CHECK_OK);
+  DoExpression* expr = factory()->NewDoExpression(block, result, pos);
+  if (!Rewriter::Rewrite(this, expr, ast_value_factory())) {
+    *ok = false;
+    return nullptr;
+  }
+  block->set_scope(block->scope()->FinalizeBlockScope());
+  return expr;
+}
+
+
+void ParserTraits::ParseArrowFunctionFormalParameterList(
+    ParserFormalParameters* parameters, Expression* expr,
+    const Scanner::Location& params_loc,
+    Scanner::Location* duplicate_loc, bool* ok) {
+  if (expr->IsEmptyParentheses()) return;
+
+  ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok);
+  if (!*ok) return;
+
+  ExpressionClassifier classifier;
+  if (!parameters->is_simple) {
+    classifier.RecordNonSimpleParameter();
+  }
+  for (int i = 0; i < parameters->Arity(); ++i) {
+    auto parameter = parameters->at(i);
+    DeclareFormalParameter(parameters->scope, parameter, &classifier);
+    if (!duplicate_loc->IsValid()) {
+      *duplicate_loc = classifier.duplicate_formal_parameter_error().location;
+    }
+  }
+  DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
+}
+
+
+void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) {
+  if (parser_->function_state_->materialized_literal_count() > 0) {
+    AstLiteralReindexer reindexer;
+
+    for (const auto p : parameters.params) {
+      if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
+      if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
+    }
+
+    DCHECK(reindexer.count() <=
+           parser_->function_state_->materialized_literal_count());
+  }
+}
+
+
+FunctionLiteral* Parser::ParseFunctionLiteral(
+    const AstRawString* function_name, Scanner::Location function_name_location,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
+    int function_token_pos, FunctionLiteral::FunctionType function_type,
+    FunctionLiteral::ArityRestriction arity_restriction,
+    LanguageMode language_mode, bool* ok) {
+  // Function ::
+  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
+  //
+  // Getter ::
+  //   '(' ')' '{' FunctionBody '}'
+  //
+  // Setter ::
+  //   '(' PropertySetParameterList ')' '{' FunctionBody '}'
+
+  int pos = function_token_pos == RelocInfo::kNoPosition
+      ? peek_position() : function_token_pos;
+
+  bool is_generator = IsGeneratorFunction(kind);
+
+  // Anonymous functions were passed either the empty symbol or a null
+  // handle as the function name.  Remember if we were passed a non-empty
+  // handle to decide whether to invoke function name inference.
+  bool should_infer_name = function_name == NULL;
+
+  // We want a non-null handle as the function name.
+  if (should_infer_name) {
+    function_name = ast_value_factory()->empty_string();
+  }
+
+  // Function declarations are function scoped in normal mode, so they are
+  // hoisted. In harmony block scoping mode they are block scoped, so they
+  // are not hoisted.
+  //
+  // One tricky case are function declarations in a local sloppy-mode eval:
+  // their declaration is hoisted, but they still see the local scope. E.g.,
+  //
+  // function() {
+  //   var x = 0
+  //   try { throw 1 } catch (x) { eval("function g() { return x }") }
+  //   return g()
+  // }
+  //
+  // needs to return 1. To distinguish such cases, we need to detect
+  // (1) whether a function stems from a sloppy eval, and
+  // (2) whether it actually hoists across the eval.
+  // Unfortunately, we do not represent sloppy eval scopes, so we do not have
+  // either information available directly, especially not when lazily compiling
+  // a function like 'g'. We hence rely on the following invariants:
+  // - (1) is the case iff the innermost scope of the deserialized scope chain
+  //   under which we compile is _not_ a declaration scope. This holds because
+  //   in all normal cases, function declarations are fully hoisted to a
+  //   declaration scope and compiled relative to that.
+  // - (2) is the case iff the current declaration scope is still the original
+  //   one relative to the deserialized scope chain. Otherwise we must be
+  //   compiling a function in an inner declaration scope in the eval, e.g. a
+  //   nested function, and hoisting works normally relative to that.
+  Scope* declaration_scope = scope_->DeclarationScope();
+  Scope* original_declaration_scope = original_scope_->DeclarationScope();
+  Scope* scope = function_type == FunctionLiteral::kDeclaration &&
+                         is_sloppy(language_mode) &&
+                         !allow_harmony_sloppy_function() &&
+                         (original_scope_ == original_declaration_scope ||
+                          declaration_scope != original_declaration_scope)
+                     ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
+                     : NewScope(scope_, FUNCTION_SCOPE, kind);
+  SetLanguageMode(scope, language_mode);
+  ZoneList<Statement*>* body = NULL;
+  int arity = -1;
+  int materialized_literal_count = -1;
+  int expected_property_count = -1;
+  DuplicateFinder duplicate_finder(scanner()->unicode_cache());
+  ExpressionClassifier formals_classifier(&duplicate_finder);
+  FunctionLiteral::EagerCompileHint eager_compile_hint =
+      parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
+                              : FunctionLiteral::kShouldLazyCompile;
+  bool should_be_used_once_hint = false;
+  // Parse function.
+  {
+    AstNodeFactory function_factory(ast_value_factory());
+    FunctionState function_state(&function_state_, &scope_, scope, kind,
+                                 &function_factory);
+    scope_->SetScopeName(function_name);
+
+    if (is_generator) {
+      // For generators, allocating variables in contexts is currently a win
+      // because it minimizes the work needed to suspend and resume an
+      // activation.
+      scope_->ForceContextAllocation();
+
+      // Calling a generator returns a generator object.  That object is stored
+      // in a temporary variable, a definition that is used by "yield"
+      // expressions. This also marks the FunctionState as a generator.
+      Variable* temp = scope_->NewTemporary(
+          ast_value_factory()->dot_generator_object_string());
+      function_state.set_generator_object_variable(temp);
+    }
+
+    Expect(Token::LPAREN, CHECK_OK);
+    int start_position = scanner()->location().beg_pos;
+    scope_->set_start_position(start_position);
+    ParserFormalParameters formals(scope);
+    ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
+    arity = formals.Arity();
+    Expect(Token::RPAREN, CHECK_OK);
+    int formals_end_position = scanner()->location().end_pos;
+
+    CheckArityRestrictions(arity, arity_restriction,
+                           formals.has_rest, start_position,
+                           formals_end_position, CHECK_OK);
+    Expect(Token::LBRACE, CHECK_OK);
+
+    // Determine if the function can be parsed lazily. Lazy parsing is different
+    // from lazy compilation; we need to parse more eagerly than we compile.
+
+    // We can only parse lazily if we also compile lazily. The heuristics for
+    // lazy compilation are:
+    // - It must not have been prohibited by the caller to Parse (some callers
+    //   need a full AST).
+    // - The outer scope must allow lazy compilation of inner functions.
+    // - The function mustn't be a function expression with an open parenthesis
+    //   before; we consider that a hint that the function will be called
+    //   immediately, and it would be a waste of time to make it lazily
+    //   compiled.
+    // These are all things we can know at this point, without looking at the
+    // function itself.
+
+    // In addition, we need to distinguish between these cases:
+    // (function foo() {
+    //   bar = function() { return 1; }
+    //  })();
+    // and
+    // (function foo() {
+    //   var a = 1;
+    //   bar = function() { return a; }
+    //  })();
+
+    // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
+    // parenthesis before the function means that it will be called
+    // immediately). The inner function *must* be parsed eagerly to resolve the
+    // possible reference to the variable in foo's scope. However, it's possible
+    // that it will be compiled lazily.
+
+    // To make this additional case work, both Parser and PreParser implement a
+    // logic where only top-level functions will be parsed lazily.
+    bool is_lazily_parsed = mode() == PARSE_LAZILY &&
+                            scope_->AllowsLazyParsing() &&
+                            !parenthesized_function_;
+    parenthesized_function_ = false;  // The bit was set for this function only.
+
+    // Eager or lazy parse?
+    // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
+    // pass it to SkipLazyFunctionBody, which may use it to abort lazy
+    // parsing if it suspect that wasn't a good idea. If so, or if we didn't
+    // try to lazy parse in the first place, we'll have to parse eagerly.
+    Scanner::BookmarkScope bookmark(scanner());
+    if (is_lazily_parsed) {
+      Scanner::BookmarkScope* maybe_bookmark =
+          bookmark.Set() ? &bookmark : nullptr;
+      SkipLazyFunctionBody(&materialized_literal_count,
+                           &expected_property_count, /*CHECK_OK*/ ok,
+                           maybe_bookmark);
+
+      materialized_literal_count += formals.materialized_literals_count +
+                                    function_state.materialized_literal_count();
+
+      if (bookmark.HasBeenReset()) {
+        // Trigger eager (re-)parsing, just below this block.
+        is_lazily_parsed = false;
+
+        // This is probably an initialization function. Inform the compiler it
+        // should also eager-compile this function, and that we expect it to be
+        // used once.
+        eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
+        should_be_used_once_hint = true;
+      }
+    }
+    if (!is_lazily_parsed) {
+      // Determine whether the function body can be discarded after parsing.
+      // The preconditions are:
+      // - Lazy compilation has to be enabled.
+      // - Neither V8 natives nor native function declarations can be allowed,
+      //   since parsing one would retroactively force the function to be
+      //   eagerly compiled.
+      // - The invoker of this parser can't depend on the AST being eagerly
+      //   built (either because the function is about to be compiled, or
+      //   because the AST is going to be inspected for some reason).
+      // - Because of the above, we can't be attempting to parse a
+      //   FunctionExpression; even without enclosing parentheses it might be
+      //   immediately invoked.
+      // - The function literal shouldn't be hinted to eagerly compile.
+      bool use_temp_zone =
+          FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() &&
+          function_type == FunctionLiteral::kDeclaration &&
+          eager_compile_hint != FunctionLiteral::kShouldEagerCompile;
+      // Open a new BodyScope, which sets our AstNodeFactory to allocate in the
+      // new temporary zone if the preconditions are satisfied, and ensures that
+      // the previous zone is always restored after parsing the body.
+      // For the purpose of scope analysis, some ZoneObjects allocated by the
+      // factory must persist after the function body is thrown away and
+      // temp_zone is deallocated. These objects are instead allocated in a
+      // parser-persistent zone (see parser_zone_ in AstNodeFactory).
+      {
+        Zone temp_zone;
+        AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone);
+
+        body = ParseEagerFunctionBody(function_name, pos, formals, kind,
+                                      function_type, CHECK_OK);
+      }
+      materialized_literal_count = function_state.materialized_literal_count();
+      expected_property_count = function_state.expected_property_count();
+      if (use_temp_zone) {
+        // If the preconditions are correct the function body should never be
+        // accessed, but do this anyway for better behaviour if they're wrong.
+        body = NULL;
+      }
+    }
+
+    // Parsing the body may change the language mode in our scope.
+    language_mode = scope->language_mode();
+
+    if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
+      if (!function_state.super_location().IsValid()) {
+        ReportMessageAt(function_name_location,
+                        MessageTemplate::kStrongSuperCallMissing,
+                        kReferenceError);
+        *ok = false;
+        return nullptr;
+      }
+    }
+
+    // Validate name and parameter names. We can do this only after parsing the
+    // function, since the function can declare itself strict.
+    CheckFunctionName(language_mode, function_name, function_name_validity,
+                      function_name_location, CHECK_OK);
+    const bool allow_duplicate_parameters =
+        is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
+    ValidateFormalParameters(&formals_classifier, language_mode,
+                             allow_duplicate_parameters, CHECK_OK);
+
+    if (is_strict(language_mode)) {
+      CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
+                              CHECK_OK);
+    }
+    if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) {
+      InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
+    }
+    if (is_strict(language_mode) || allow_harmony_sloppy() ||
+        allow_harmony_destructuring_bind()) {
+      CheckConflictingVarDeclarations(scope, CHECK_OK);
+    }
+
+    if (body) {
+      // If body can be inspected, rewrite queued destructuring assignments
+      ParserTraits::RewriteDestructuringAssignments();
+    }
+  }
+
+  bool has_duplicate_parameters =
+      !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
+  FunctionLiteral::ParameterFlag duplicate_parameters =
+      has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
+                               : FunctionLiteral::kNoDuplicateParameters;
+
+  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
+      function_name, scope, body, materialized_literal_count,
+      expected_property_count, arity, duplicate_parameters, function_type,
+      eager_compile_hint, kind, pos);
+  function_literal->set_function_token_position(function_token_pos);
+  if (should_be_used_once_hint)
+    function_literal->set_should_be_used_once_hint();
+
+  if (scope->has_rest_parameter()) {
+    function_literal->set_dont_optimize_reason(kRestParameter);
+  }
+
+  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
+  return function_literal;
+}
+
+
+void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
+                                  int* expected_property_count, bool* ok,
+                                  Scanner::BookmarkScope* bookmark) {
+  DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
+  if (produce_cached_parse_data()) CHECK(log_);
+
+  int function_block_pos = position();
+  if (consume_cached_parse_data() && !cached_parse_data_->rejected()) {
+    // If we have cached data, we use it to skip parsing the function body. The
+    // data contains the information we need to construct the lazy function.
+    FunctionEntry entry =
+        cached_parse_data_->GetFunctionEntry(function_block_pos);
+    // Check that cached data is valid. If not, mark it as invalid (the embedder
+    // handles it). Note that end position greater than end of stream is safe,
+    // and hard to check.
+    if (entry.is_valid() && entry.end_pos() > function_block_pos) {
+      scanner()->SeekForward(entry.end_pos() - 1);
+
+      scope_->set_end_position(entry.end_pos());
+      Expect(Token::RBRACE, ok);
+      if (!*ok) {
+        return;
+      }
+      total_preparse_skipped_ += scope_->end_position() - function_block_pos;
+      *materialized_literal_count = entry.literal_count();
+      *expected_property_count = entry.property_count();
+      SetLanguageMode(scope_, entry.language_mode());
+      if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
+      if (entry.calls_eval()) scope_->RecordEvalCall();
+      return;
+    }
+    cached_parse_data_->Reject();
+  }
+  // With no cached data, we partially parse the function, without building an
+  // AST. This gathers the data needed to build a lazy function.
+  SingletonLogger logger;
+  PreParser::PreParseResult result =
+      ParseLazyFunctionBodyWithPreParser(&logger, bookmark);
+  if (bookmark && bookmark->HasBeenReset()) {
+    return;  // Return immediately if pre-parser devided to abort parsing.
+  }
+  if (result == PreParser::kPreParseStackOverflow) {
+    // Propagate stack overflow.
+    set_stack_overflow();
+    *ok = false;
+    return;
+  }
+  if (logger.has_error()) {
+    ParserTraits::ReportMessageAt(
+        Scanner::Location(logger.start(), logger.end()), logger.message(),
+        logger.argument_opt(), logger.error_type());
+    *ok = false;
+    return;
+  }
+  scope_->set_end_position(logger.end());
+  Expect(Token::RBRACE, ok);
+  if (!*ok) {
+    return;
+  }
+  total_preparse_skipped_ += scope_->end_position() - function_block_pos;
+  *materialized_literal_count = logger.literals();
+  *expected_property_count = logger.properties();
+  SetLanguageMode(scope_, logger.language_mode());
+  if (logger.uses_super_property()) {
+    scope_->RecordSuperPropertyUsage();
+  }
+  if (logger.calls_eval()) {
+    scope_->RecordEvalCall();
+  }
+  if (produce_cached_parse_data()) {
+    DCHECK(log_);
+    // Position right after terminal '}'.
+    int body_end = scanner()->location().end_pos;
+    log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
+                      *expected_property_count, scope_->language_mode(),
+                      scope_->uses_super_property(), scope_->calls_eval());
+  }
+}
+
+
+Statement* Parser::BuildAssertIsCoercible(Variable* var) {
+  // if (var === null || var === undefined)
+  //     throw /* type error kNonCoercible) */;
+
+  Expression* condition = factory()->NewBinaryOperation(
+      Token::OR, factory()->NewCompareOperation(
+                     Token::EQ_STRICT, factory()->NewVariableProxy(var),
+                     factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+                     RelocInfo::kNoPosition),
+      factory()->NewCompareOperation(
+          Token::EQ_STRICT, factory()->NewVariableProxy(var),
+          factory()->NewNullLiteral(RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition),
+      RelocInfo::kNoPosition);
+  Expression* throw_type_error = this->NewThrowTypeError(
+      MessageTemplate::kNonCoercible, ast_value_factory()->empty_string(),
+      RelocInfo::kNoPosition);
+  IfStatement* if_statement = factory()->NewIfStatement(
+      condition, factory()->NewExpressionStatement(throw_type_error,
+                                                   RelocInfo::kNoPosition),
+      factory()->NewEmptyStatement(RelocInfo::kNoPosition),
+      RelocInfo::kNoPosition);
+  return if_statement;
+}
+
+
+class InitializerRewriter : public AstExpressionVisitor {
+ public:
+  InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser,
+                      Scope* scope)
+      : AstExpressionVisitor(stack_limit, root),
+        parser_(parser),
+        scope_(scope) {}
+
+ private:
+  void VisitExpression(Expression* expr) {
+    RewritableAssignmentExpression* to_rewrite =
+        expr->AsRewritableAssignmentExpression();
+    if (to_rewrite == nullptr || to_rewrite->is_rewritten()) return;
+
+    Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite,
+                                                            scope_);
+  }
+
+ private:
+  Parser* parser_;
+  Scope* scope_;
+};
+
+
+void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) {
+  InitializerRewriter rewriter(stack_limit_, expr, this, scope);
+  rewriter.Run();
+}
+
+
+Block* Parser::BuildParameterInitializationBlock(
+    const ParserFormalParameters& parameters, bool* ok) {
+  DCHECK(!parameters.is_simple);
+  DCHECK(scope_->is_function_scope());
+  Block* init_block =
+      factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
+  for (int i = 0; i < parameters.params.length(); ++i) {
+    auto parameter = parameters.params[i];
+    if (parameter.is_rest && parameter.pattern->IsVariableProxy()) break;
+    DeclarationDescriptor descriptor;
+    descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
+    descriptor.parser = this;
+    descriptor.scope = scope_;
+    descriptor.hoist_scope = nullptr;
+    descriptor.mode = LET;
+    descriptor.needs_init = true;
+    descriptor.declaration_pos = parameter.pattern->position();
+    // The position that will be used by the AssignmentExpression
+    // which copies from the temp parameter to the pattern.
+    //
+    // TODO(adamk): Should this be RelocInfo::kNoPosition, since
+    // it's just copying from a temp var to the real param var?
+    descriptor.initialization_pos = parameter.pattern->position();
+    // The initializer position which will end up in,
+    // Variable::initializer_position(), used for hole check elimination.
+    int initializer_position = parameter.pattern->position();
+    Expression* initial_value =
+        factory()->NewVariableProxy(parameters.scope->parameter(i));
+    if (parameter.initializer != nullptr) {
+      // IS_UNDEFINED($param) ? initializer : $param
+
+      // Ensure initializer is rewritten
+      RewriteParameterInitializer(parameter.initializer, scope_);
+
+      auto condition = factory()->NewCompareOperation(
+          Token::EQ_STRICT,
+          factory()->NewVariableProxy(parameters.scope->parameter(i)),
+          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition);
+      initial_value = factory()->NewConditional(
+          condition, parameter.initializer, initial_value,
+          RelocInfo::kNoPosition);
+      descriptor.initialization_pos = parameter.initializer->position();
+      initializer_position = parameter.initializer_end_position;
+    }
+
+    Scope* param_scope = scope_;
+    Block* param_block = init_block;
+    if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
+      param_scope = NewScope(scope_, BLOCK_SCOPE);
+      param_scope->set_is_declaration_scope();
+      param_scope->set_start_position(parameter.pattern->position());
+      param_scope->set_end_position(RelocInfo::kNoPosition);
+      param_scope->RecordEvalCall();
+      param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
+      param_block->set_scope(param_scope);
+      descriptor.hoist_scope = scope_;
+    }
+
+    {
+      BlockState block_state(&scope_, param_scope);
+      DeclarationParsingResult::Declaration decl(
+          parameter.pattern, initializer_position, initial_value);
+      PatternRewriter::DeclareAndInitializeVariables(param_block, &descriptor,
+                                                     &decl, nullptr, CHECK_OK);
+    }
+
+    if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
+      param_scope = param_scope->FinalizeBlockScope();
+      if (param_scope != nullptr) {
+        CheckConflictingVarDeclarations(param_scope, CHECK_OK);
+      }
+      init_block->statements()->Add(param_block, zone());
+    }
+  }
+  return init_block;
+}
+
+
+ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
+    const AstRawString* function_name, int pos,
+    const ParserFormalParameters& parameters, FunctionKind kind,
+    FunctionLiteral::FunctionType function_type, bool* ok) {
+  // Everything inside an eagerly parsed function will be parsed eagerly
+  // (see comment above).
+  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
+  ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
+
+  static const int kFunctionNameAssignmentIndex = 0;
+  if (function_type == FunctionLiteral::kNamedExpression) {
+    DCHECK(function_name != NULL);
+    // If we have a named function expression, we add a local variable
+    // declaration to the body of the function with the name of the
+    // function and let it refer to the function itself (closure).
+    // Not having parsed the function body, the language mode may still change,
+    // so we reserve a spot and create the actual const assignment later.
+    DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
+    result->Add(NULL, zone());
+  }
+
+  ZoneList<Statement*>* body = result;
+  Scope* inner_scope = scope_;
+  Block* inner_block = nullptr;
+  if (!parameters.is_simple) {
+    inner_scope = NewScope(scope_, BLOCK_SCOPE);
+    inner_scope->set_is_declaration_scope();
+    inner_scope->set_start_position(scanner()->location().beg_pos);
+    inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
+    inner_block->set_scope(inner_scope);
+    body = inner_block->statements();
+  }
+
+  {
+    BlockState block_state(&scope_, inner_scope);
+
+    // For generators, allocate and yield an iterator on function entry.
+    if (IsGeneratorFunction(kind)) {
+      ZoneList<Expression*>* arguments =
+          new(zone()) ZoneList<Expression*>(0, zone());
+      CallRuntime* allocation = factory()->NewCallRuntime(
+          Runtime::kCreateJSGeneratorObject, arguments, pos);
+      VariableProxy* init_proxy = factory()->NewVariableProxy(
+          function_state_->generator_object_variable());
+      Assignment* assignment = factory()->NewAssignment(
+          Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
+      VariableProxy* get_proxy = factory()->NewVariableProxy(
+          function_state_->generator_object_variable());
+      Yield* yield = factory()->NewYield(
+          get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
+      body->Add(factory()->NewExpressionStatement(
+          yield, RelocInfo::kNoPosition), zone());
+    }
+
+    ParseStatementList(body, Token::RBRACE, CHECK_OK);
+
+    if (IsGeneratorFunction(kind)) {
+      VariableProxy* get_proxy = factory()->NewVariableProxy(
+          function_state_->generator_object_variable());
+      Expression* undefined =
+          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
+      Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
+                                         RelocInfo::kNoPosition);
+      body->Add(factory()->NewExpressionStatement(
+          yield, RelocInfo::kNoPosition), zone());
+    }
+
+    if (IsSubclassConstructor(kind)) {
+      body->Add(
+          factory()->NewReturnStatement(
+              this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
+              RelocInfo::kNoPosition),
+              zone());
+    }
+  }
+
+  Expect(Token::RBRACE, CHECK_OK);
+  scope_->set_end_position(scanner()->location().end_pos);
+
+  if (!parameters.is_simple) {
+    DCHECK_NOT_NULL(inner_scope);
+    DCHECK_EQ(body, inner_block->statements());
+    SetLanguageMode(scope_, inner_scope->language_mode());
+    Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
+    DCHECK_NOT_NULL(init_block);
+
+    inner_scope->set_end_position(scanner()->location().end_pos);
+    inner_scope = inner_scope->FinalizeBlockScope();
+    if (inner_scope != nullptr) {
+      CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
+      InsertShadowingVarBindingInitializers(inner_block);
+    }
+
+    result->Add(init_block, zone());
+    result->Add(inner_block, zone());
+  }
+
+  if (function_type == FunctionLiteral::kNamedExpression) {
+    // Now that we know the language mode, we can create the const assignment
+    // in the previously reserved spot.
+    // NOTE: We create a proxy and resolve it here so that in the
+    // future we can change the AST to only refer to VariableProxies
+    // instead of Variables and Proxies as is the case now.
+    VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY;
+    Variable* fvar = new (zone())
+        Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
+                 kCreatedInitialized, kNotAssigned);
+    VariableProxy* proxy = factory()->NewVariableProxy(fvar);
+    VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
+        proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
+    scope_->DeclareFunctionVar(fvar_declaration);
+
+    VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
+    result->Set(kFunctionNameAssignmentIndex,
+                factory()->NewExpressionStatement(
+                    factory()->NewAssignment(Token::INIT, fproxy,
+                                             factory()->NewThisFunction(pos),
+                                             RelocInfo::kNoPosition),
+                    RelocInfo::kNoPosition));
+  }
+
+  return result;
+}
+
+
+PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
+    SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
+  // This function may be called on a background thread too; record only the
+  // main thread preparse times.
+  if (pre_parse_timer_ != NULL) {
+    pre_parse_timer_->Start();
+  }
+  DCHECK_EQ(Token::LBRACE, scanner()->current_token());
+
+  if (reusable_preparser_ == NULL) {
+    reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
+                                        NULL, stack_limit_);
+    reusable_preparser_->set_allow_lazy(true);
+#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
+    SET_ALLOW(natives);
+    SET_ALLOW(harmony_sloppy);
+    SET_ALLOW(harmony_sloppy_let);
+    SET_ALLOW(harmony_default_parameters);
+    SET_ALLOW(harmony_destructuring_bind);
+    SET_ALLOW(harmony_destructuring_assignment);
+    SET_ALLOW(strong_mode);
+    SET_ALLOW(harmony_do_expressions);
+    SET_ALLOW(harmony_function_name);
+#undef SET_ALLOW
+  }
+  PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
+      language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
+      logger, bookmark);
+  if (pre_parse_timer_ != NULL) {
+    pre_parse_timer_->Stop();
+  }
+  return result;
+}
+
+
+ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
+                                        Scanner::Location class_name_location,
+                                        bool name_is_strict_reserved, int pos,
+                                        bool* ok) {
+  // All parts of a ClassDeclaration and ClassExpression are strict code.
+  if (name_is_strict_reserved) {
+    ReportMessageAt(class_name_location,
+                    MessageTemplate::kUnexpectedStrictReserved);
+    *ok = false;
+    return NULL;
+  }
+  if (IsEvalOrArguments(name)) {
+    ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
+    *ok = false;
+    return NULL;
+  }
+  if (is_strong(language_mode()) && IsUndefined(name)) {
+    ReportMessageAt(class_name_location, MessageTemplate::kStrongUndefined);
+    *ok = false;
+    return NULL;
+  }
+
+  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
+  BlockState block_state(&scope_, block_scope);
+  RaiseLanguageMode(STRICT);
+  scope_->SetScopeName(name);
+
+  VariableProxy* proxy = NULL;
+  if (name != NULL) {
+    proxy = NewUnresolved(name, CONST);
+    const bool is_class_declaration = true;
+    Declaration* declaration = factory()->NewVariableDeclaration(
+        proxy, CONST, block_scope, pos, is_class_declaration,
+        scope_->class_declaration_group_start());
+    Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
+  }
+
+  Expression* extends = NULL;
+  if (Check(Token::EXTENDS)) {
+    block_scope->set_start_position(scanner()->location().end_pos);
+    ExpressionClassifier classifier;
+    extends = ParseLeftHandSideExpression(&classifier, CHECK_OK);
+    extends = ParserTraits::RewriteNonPattern(extends, &classifier, CHECK_OK);
+  } else {
+    block_scope->set_start_position(scanner()->location().end_pos);
+  }
+
+
+  ClassLiteralChecker checker(this);
+  ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone());
+  FunctionLiteral* constructor = NULL;
+  bool has_seen_constructor = false;
+
+  Expect(Token::LBRACE, CHECK_OK);
+
+  const bool has_extends = extends != nullptr;
+  while (peek() != Token::RBRACE) {
+    if (Check(Token::SEMICOLON)) continue;
+    FuncNameInferrer::State fni_state(fni_);
+    const bool in_class = true;
+    const bool is_static = false;
+    bool is_computed_name = false;  // Classes do not care about computed
+                                    // property names here.
+    ExpressionClassifier classifier;
+    const AstRawString* name = nullptr;
+    ObjectLiteral::Property* property = ParsePropertyDefinition(
+        &checker, in_class, has_extends, is_static, &is_computed_name,
+        &has_seen_constructor, &classifier, &name, CHECK_OK);
+    property = ParserTraits::RewriteNonPatternObjectLiteralProperty(
+        property, &classifier, CHECK_OK);
+
+    if (has_seen_constructor && constructor == NULL) {
+      constructor = GetPropertyValue(property)->AsFunctionLiteral();
+      DCHECK_NOT_NULL(constructor);
+    } else {
+      properties->Add(property, zone());
+    }
+
+    if (fni_ != NULL) fni_->Infer();
+
+    if (allow_harmony_function_name()) {
+      SetFunctionNameFromPropertyName(property, name);
+    }
+  }
+
+  Expect(Token::RBRACE, CHECK_OK);
+  int end_pos = scanner()->location().end_pos;
+
+  if (constructor == NULL) {
+    constructor = DefaultConstructor(extends != NULL, block_scope, pos, end_pos,
+                                     block_scope->language_mode());
+  }
+
+  // Note that we do not finalize this block scope because strong
+  // mode uses it as a sentinel value indicating an anonymous class.
+  block_scope->set_end_position(end_pos);
+
+  if (name != NULL) {
+    DCHECK_NOT_NULL(proxy);
+    proxy->var()->set_initializer_position(end_pos);
+  }
+
+  return factory()->NewClassLiteral(name, block_scope, proxy, extends,
+                                    constructor, properties, pos, end_pos);
+}
+
+
+Expression* Parser::ParseV8Intrinsic(bool* ok) {
+  // CallRuntime ::
+  //   '%' Identifier Arguments
+
+  int pos = peek_position();
+  Expect(Token::MOD, CHECK_OK);
+  // Allow "eval" or "arguments" for backward compatibility.
+  const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers,
+                                             CHECK_OK);
+  Scanner::Location spread_pos;
+  ExpressionClassifier classifier;
+  ZoneList<Expression*>* args =
+      ParseArguments(&spread_pos, &classifier, CHECK_OK);
+  args = RewriteNonPatternArguments(args, &classifier, CHECK_OK);
+
+  DCHECK(!spread_pos.IsValid());
+
+  if (extension_ != NULL) {
+    // The extension structures are only accessible while parsing the
+    // very first time not when reparsing because of lazy compilation.
+    scope_->DeclarationScope()->ForceEagerCompilation();
+  }
+
+  const Runtime::Function* function = Runtime::FunctionForName(name->string());
+
+  if (function != NULL) {
+    // Check for possible name clash.
+    DCHECK_EQ(Context::kNotFound,
+              Context::IntrinsicIndexForName(name->string()));
+    // Check for built-in IS_VAR macro.
+    if (function->function_id == Runtime::kIS_VAR) {
+      DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
+      // %IS_VAR(x) evaluates to x if x is a variable,
+      // leads to a parse error otherwise.  Could be implemented as an
+      // inline function %_IS_VAR(x) to eliminate this special case.
+      if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
+        return args->at(0);
+      } else {
+        ReportMessage(MessageTemplate::kNotIsvar);
+        *ok = false;
+        return NULL;
+      }
+    }
+
+    // Check that the expected number of arguments are being passed.
+    if (function->nargs != -1 && function->nargs != args->length()) {
+      ReportMessage(MessageTemplate::kIllegalAccess);
+      *ok = false;
+      return NULL;
+    }
+
+    return factory()->NewCallRuntime(function, args, pos);
+  }
+
+  int context_index = Context::IntrinsicIndexForName(name->string());
+
+  // Check that the function is defined.
+  if (context_index == Context::kNotFound) {
+    ParserTraits::ReportMessage(MessageTemplate::kNotDefined, name);
+    *ok = false;
+    return NULL;
+  }
+
+  return factory()->NewCallRuntime(context_index, args, pos);
+}
+
+
+Literal* Parser::GetLiteralUndefined(int position) {
+  return factory()->NewUndefinedLiteral(position);
+}
+
+
+void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
+  Declaration* decl = scope->CheckConflictingVarDeclarations();
+  if (decl != NULL) {
+    // In ES6, conflicting variable bindings are early errors.
+    const AstRawString* name = decl->proxy()->raw_name();
+    int position = decl->proxy()->position();
+    Scanner::Location location = position == RelocInfo::kNoPosition
+        ? Scanner::Location::invalid()
+        : Scanner::Location(position, position + 1);
+    ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration,
+                                  name);
+    *ok = false;
+  }
+}
+
+
+void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
+  // For each var-binding that shadows a parameter, insert an assignment
+  // initializing the variable with the parameter.
+  Scope* inner_scope = inner_block->scope();
+  DCHECK(inner_scope->is_declaration_scope());
+  Scope* function_scope = inner_scope->outer_scope();
+  DCHECK(function_scope->is_function_scope());
+  ZoneList<Declaration*>* decls = inner_scope->declarations();
+  for (int i = 0; i < decls->length(); ++i) {
+    Declaration* decl = decls->at(i);
+    if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue;
+    const AstRawString* name = decl->proxy()->raw_name();
+    Variable* parameter = function_scope->LookupLocal(name);
+    if (parameter == nullptr) continue;
+    VariableProxy* to = inner_scope->NewUnresolved(factory(), name);
+    VariableProxy* from = factory()->NewVariableProxy(parameter);
+    Expression* assignment = factory()->NewAssignment(
+        Token::ASSIGN, to, from, RelocInfo::kNoPosition);
+    Statement* statement = factory()->NewExpressionStatement(
+        assignment, RelocInfo::kNoPosition);
+    inner_block->statements()->InsertAt(0, statement, zone());
+  }
+}
+
+
+void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) {
+  // For each variable which is used as a function declaration in a sloppy
+  // block,
+  DCHECK(scope->is_declaration_scope());
+  SloppyBlockFunctionMap* map = scope->sloppy_block_function_map();
+  for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
+    AstRawString* name = static_cast<AstRawString*>(p->key);
+    // If the variable wouldn't conflict with a lexical declaration,
+    Variable* var = scope->LookupLocal(name);
+    if (var == nullptr || !IsLexicalVariableMode(var->mode())) {
+      // Declare a var-style binding for the function in the outer scope
+      VariableProxy* proxy = scope->NewUnresolved(factory(), name);
+      Declaration* declaration = factory()->NewVariableDeclaration(
+          proxy, VAR, scope, RelocInfo::kNoPosition);
+      Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope);
+      DCHECK(ok);  // Based on the preceding check, this should not fail
+      if (!ok) return;
+
+      // Write in assignments to var for each block-scoped function declaration
+      auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value);
+      for (SloppyBlockFunctionStatement* delegate : *delegates) {
+        // Read from the local lexical scope and write to the function scope
+        VariableProxy* to = scope->NewUnresolved(factory(), name);
+        VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
+        Expression* assignment = factory()->NewAssignment(
+            Token::ASSIGN, to, from, RelocInfo::kNoPosition);
+        Statement* statement = factory()->NewExpressionStatement(
+            assignment, RelocInfo::kNoPosition);
+        delegate->set_statement(statement);
+      }
+    }
+  }
+}
+
+
+// ----------------------------------------------------------------------------
+// Parser support
+
+bool Parser::TargetStackContainsLabel(const AstRawString* label) {
+  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
+    if (ContainsLabel(t->statement()->labels(), label)) return true;
+  }
+  return false;
+}
+
+
+BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
+                                              bool* ok) {
+  bool anonymous = label == NULL;
+  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
+    BreakableStatement* stat = t->statement();
+    if ((anonymous && stat->is_target_for_anonymous()) ||
+        (!anonymous && ContainsLabel(stat->labels(), label))) {
+      return stat;
+    }
+  }
+  return NULL;
+}
+
+
+IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
+                                                 bool* ok) {
+  bool anonymous = label == NULL;
+  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
+    IterationStatement* stat = t->statement()->AsIterationStatement();
+    if (stat == NULL) continue;
+
+    DCHECK(stat->is_target_for_anonymous());
+    if (anonymous || ContainsLabel(stat->labels(), label)) {
+      return stat;
+    }
+  }
+  return NULL;
+}
+
+
+void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
+  if (scanner_.source_url()->length() > 0) {
+    Handle<String> source_url = scanner_.source_url()->Internalize(isolate);
+    script->set_source_url(*source_url);
+  }
+  if (scanner_.source_mapping_url()->length() > 0) {
+    Handle<String> source_mapping_url =
+        scanner_.source_mapping_url()->Internalize(isolate);
+    script->set_source_mapping_url(*source_mapping_url);
+  }
+}
+
+
+void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
+  // Internalize strings.
+  ast_value_factory()->Internalize(isolate);
+
+  // Error processing.
+  if (error) {
+    if (stack_overflow()) {
+      isolate->StackOverflow();
+    } else {
+      DCHECK(pending_error_handler_.has_pending_error());
+      pending_error_handler_.ThrowPendingError(isolate, script);
+    }
+  }
+
+  // Move statistics to Isolate.
+  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
+       ++feature) {
+    for (int i = 0; i < use_counts_[feature]; ++i) {
+      isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
+    }
+  }
+  isolate->counters()->total_preparse_skipped()->Increment(
+      total_preparse_skipped_);
+}
+
+
+// ----------------------------------------------------------------------------
+// The Parser interface.
+
+
+bool Parser::ParseStatic(ParseInfo* info) {
+  Parser parser(info);
+  if (parser.Parse(info)) {
+    info->set_language_mode(info->literal()->language_mode());
+    return true;
+  }
+  return false;
+}
+
+
+bool Parser::Parse(ParseInfo* info) {
+  DCHECK(info->literal() == NULL);
+  FunctionLiteral* result = NULL;
+  // Ok to use Isolate here; this function is only called in the main thread.
+  DCHECK(parsing_on_main_thread_);
+  Isolate* isolate = info->isolate();
+  pre_parse_timer_ = isolate->counters()->pre_parse();
+  if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
+    // If intrinsics are allowed, the Parser cannot operate independent of the
+    // V8 heap because of Runtime. Tell the string table to internalize strings
+    // and values right after they're created.
+    ast_value_factory()->Internalize(isolate);
+  }
+
+  if (info->is_lazy()) {
+    DCHECK(!info->is_eval());
+    if (info->shared_info()->is_function()) {
+      result = ParseLazy(isolate, info);
+    } else {
+      result = ParseProgram(isolate, info);
+    }
+  } else {
+    SetCachedData(info);
+    result = ParseProgram(isolate, info);
+  }
+  info->set_literal(result);
+
+  Internalize(isolate, info->script(), result == NULL);
+  DCHECK(ast_value_factory()->IsInternalized());
+  return (result != NULL);
+}
+
+
+void Parser::ParseOnBackground(ParseInfo* info) {
+  parsing_on_main_thread_ = false;
+
+  DCHECK(info->literal() == NULL);
+  FunctionLiteral* result = NULL;
+  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
+
+  CompleteParserRecorder recorder;
+  if (produce_cached_parse_data()) log_ = &recorder;
+
+  DCHECK(info->source_stream() != NULL);
+  ExternalStreamingStream stream(info->source_stream(),
+                                 info->source_stream_encoding());
+  scanner_.Initialize(&stream);
+  DCHECK(info->context().is_null() || info->context()->IsNativeContext());
+
+  // When streaming, we don't know the length of the source until we have parsed
+  // it. The raw data can be UTF-8, so we wouldn't know the source length until
+  // we have decoded it anyway even if we knew the raw data length (which we
+  // don't). We work around this by storing all the scopes which need their end
+  // position set at the end of the script (the top scope and possible eval
+  // scopes) and set their end position after we know the script length.
+  result = DoParseProgram(info);
+
+  info->set_literal(result);
+
+  // We cannot internalize on a background thread; a foreground task will take
+  // care of calling Parser::Internalize just before compilation.
+
+  if (produce_cached_parse_data()) {
+    if (result != NULL) *info->cached_data() = recorder.GetScriptData();
+    log_ = NULL;
+  }
+}
+
+
+ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
+  return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
+}
+
+
+void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
+  int pos = scanner()->location().beg_pos;
+  int end = scanner()->location().end_pos - (tail ? 1 : 2);
+  const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
+  const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
+  Literal* cooked = factory()->NewStringLiteral(tv, pos);
+  Literal* raw = factory()->NewStringLiteral(trv, pos);
+  (*state)->AddTemplateSpan(cooked, raw, end, zone());
+}
+
+
+void Parser::AddTemplateExpression(TemplateLiteralState* state,
+                                   Expression* expression) {
+  (*state)->AddExpression(expression, zone());
+}
+
+
+Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
+                                         Expression* tag) {
+  TemplateLiteral* lit = *state;
+  int pos = lit->position();
+  const ZoneList<Expression*>* cooked_strings = lit->cooked();
+  const ZoneList<Expression*>* raw_strings = lit->raw();
+  const ZoneList<Expression*>* expressions = lit->expressions();
+  DCHECK_EQ(cooked_strings->length(), raw_strings->length());
+  DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
+
+  if (!tag) {
+    // Build tree of BinaryOps to simplify code-generation
+    Expression* expr = cooked_strings->at(0);
+    int i = 0;
+    while (i < expressions->length()) {
+      Expression* sub = expressions->at(i++);
+      Expression* cooked_str = cooked_strings->at(i);
+
+      // Let middle be ToString(sub).
+      ZoneList<Expression*>* args =
+          new (zone()) ZoneList<Expression*>(1, zone());
+      args->Add(sub, zone());
+      Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString,
+                                                     args, sub->position());
+
+      expr = factory()->NewBinaryOperation(
+          Token::ADD, factory()->NewBinaryOperation(
+                          Token::ADD, expr, middle, expr->position()),
+          cooked_str, sub->position());
+    }
+    return expr;
+  } else {
+    uint32_t hash = ComputeTemplateLiteralHash(lit);
+
+    int cooked_idx = function_state_->NextMaterializedLiteralIndex();
+    int raw_idx = function_state_->NextMaterializedLiteralIndex();
+
+    // $getTemplateCallSite
+    ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
+    args->Add(factory()->NewArrayLiteral(
+                  const_cast<ZoneList<Expression*>*>(cooked_strings),
+                  cooked_idx, is_strong(language_mode()), pos),
+              zone());
+    args->Add(
+        factory()->NewArrayLiteral(
+            const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx,
+            is_strong(language_mode()), pos),
+        zone());
+
+    // Ensure hash is suitable as a Smi value
+    Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash)));
+    args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone());
+
+    Expression* call_site = factory()->NewCallRuntime(
+        Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start);
+
+    // Call TagFn
+    ZoneList<Expression*>* call_args =
+        new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
+    call_args->Add(call_site, zone());
+    call_args->AddAll(*expressions, zone());
+    return factory()->NewCall(tag, call_args, pos);
+  }
+}
+
+
+uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
+  const ZoneList<Expression*>* raw_strings = lit->raw();
+  int total = raw_strings->length();
+  DCHECK(total);
+
+  uint32_t running_hash = 0;
+
+  for (int index = 0; index < total; ++index) {
+    if (index) {
+      running_hash = StringHasher::ComputeRunningHashOneByte(
+          running_hash, "${}", 3);
+    }
+
+    const AstRawString* raw_string =
+        raw_strings->at(index)->AsLiteral()->raw_value()->AsString();
+    if (raw_string->is_one_byte()) {
+      const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
+      running_hash = StringHasher::ComputeRunningHashOneByte(
+          running_hash, data, raw_string->length());
+    } else {
+      const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
+      running_hash = StringHasher::ComputeRunningHash(running_hash, data,
+                                                      raw_string->length());
+    }
+  }
+
+  return running_hash;
+}
+
+
+ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
+    ZoneList<v8::internal::Expression*>* list) {
+  ZoneList<v8::internal::Expression*>* args =
+      new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
+  if (list->length() == 1) {
+    // Spread-call with single spread argument produces an InternalArray
+    // containing the values from the array.
+    //
+    // Function is called or constructed with the produced array of arguments
+    //
+    // EG: Apply(Func, Spread(spread0))
+    ZoneList<Expression*>* spread_list =
+        new (zone()) ZoneList<Expression*>(0, zone());
+    spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
+    args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
+                                        spread_list, RelocInfo::kNoPosition),
+              zone());
+    return args;
+  } else {
+    // Spread-call with multiple arguments produces array literals for each
+    // sequences of unspread arguments, and converts each spread iterable to
+    // an Internal array. Finally, all of these produced arrays are flattened
+    // into a single InternalArray, containing the arguments for the call.
+    //
+    // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
+    //                         Spread(spread1), [unspread2, unspread3]))
+    int i = 0;
+    int n = list->length();
+    while (i < n) {
+      if (!list->at(i)->IsSpread()) {
+        ZoneList<v8::internal::Expression*>* unspread =
+            new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
+
+        // Push array of unspread parameters
+        while (i < n && !list->at(i)->IsSpread()) {
+          unspread->Add(list->at(i++), zone());
+        }
+        int literal_index = function_state_->NextMaterializedLiteralIndex();
+        args->Add(factory()->NewArrayLiteral(unspread, literal_index,
+                                             is_strong(language_mode()),
+                                             RelocInfo::kNoPosition),
+                  zone());
+
+        if (i == n) break;
+      }
+
+      // Push eagerly spread argument
+      ZoneList<v8::internal::Expression*>* spread_list =
+          new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
+      spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
+      args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
+                                          spread_list, RelocInfo::kNoPosition),
+                zone());
+    }
+
+    list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
+    list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
+                                        RelocInfo::kNoPosition),
+              zone());
+    return list;
+  }
+  UNREACHABLE();
+}
+
+
+Expression* Parser::SpreadCall(Expression* function,
+                               ZoneList<v8::internal::Expression*>* args,
+                               int pos) {
+  if (function->IsSuperCallReference()) {
+    // Super calls
+    // $super_constructor = %_GetSuperConstructor(<this-function>)
+    // %reflect_construct($super_constructor, args, new.target)
+    ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
+    tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
+    Expression* super_constructor = factory()->NewCallRuntime(
+        Runtime::kInlineGetSuperConstructor, tmp, pos);
+    args->InsertAt(0, super_constructor, zone());
+    args->Add(function->AsSuperCallReference()->new_target_var(), zone());
+    return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
+                                     pos);
+  } else {
+    if (function->IsProperty()) {
+      // Method calls
+      if (function->AsProperty()->IsSuperAccess()) {
+        Expression* home =
+            ThisExpression(scope_, factory(), RelocInfo::kNoPosition);
+        args->InsertAt(0, function, zone());
+        args->InsertAt(1, home, zone());
+      } else {
+        Variable* temp =
+            scope_->NewTemporary(ast_value_factory()->empty_string());
+        VariableProxy* obj = factory()->NewVariableProxy(temp);
+        Assignment* assign_obj = factory()->NewAssignment(
+            Token::ASSIGN, obj, function->AsProperty()->obj(),
+            RelocInfo::kNoPosition);
+        function = factory()->NewProperty(
+            assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition);
+        args->InsertAt(0, function, zone());
+        obj = factory()->NewVariableProxy(temp);
+        args->InsertAt(1, obj, zone());
+      }
+    } else {
+      // Non-method calls
+      args->InsertAt(0, function, zone());
+      args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+                     zone());
+    }
+    return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
+  }
+}
+
+
+Expression* Parser::SpreadCallNew(Expression* function,
+                                  ZoneList<v8::internal::Expression*>* args,
+                                  int pos) {
+  args->InsertAt(0, function, zone());
+
+  return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
+}
+
+
+void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
+  v8::Isolate::UseCounterFeature feature;
+  if (is_sloppy(mode))
+    feature = v8::Isolate::kSloppyMode;
+  else if (is_strong(mode))
+    feature = v8::Isolate::kStrongMode;
+  else if (is_strict(mode))
+    feature = v8::Isolate::kStrictMode;
+  else
+    UNREACHABLE();
+  ++use_counts_[feature];
+  scope->SetLanguageMode(mode);
+}
+
+
+void Parser::RaiseLanguageMode(LanguageMode mode) {
+  SetLanguageMode(scope_,
+                  static_cast<LanguageMode>(scope_->language_mode() | mode));
+}
+
+
+void ParserTraits::RewriteDestructuringAssignments() {
+  parser_->RewriteDestructuringAssignments();
+}
+
+
+Expression* ParserTraits::RewriteNonPattern(
+    Expression* expr, const ExpressionClassifier* classifier, bool* ok) {
+  return parser_->RewriteNonPattern(expr, classifier, ok);
+}
+
+
+ZoneList<Expression*>* ParserTraits::RewriteNonPatternArguments(
+    ZoneList<Expression*>* args, const ExpressionClassifier* classifier,
+    bool* ok) {
+  return parser_->RewriteNonPatternArguments(args, classifier, ok);
+}
+
+
+ObjectLiteralProperty* ParserTraits::RewriteNonPatternObjectLiteralProperty(
+    ObjectLiteralProperty* property, const ExpressionClassifier* classifier,
+    bool* ok) {
+  return parser_->RewriteNonPatternObjectLiteralProperty(property, classifier,
+                                                         ok);
+}
+
+
+Expression* Parser::RewriteNonPattern(Expression* expr,
+                                      const ExpressionClassifier* classifier,
+                                      bool* ok) {
+  // For the time being, this does no rewriting at all.
+  ValidateExpression(classifier, ok);
+  return expr;
+}
+
+
+ZoneList<Expression*>* Parser::RewriteNonPatternArguments(
+    ZoneList<Expression*>* args, const ExpressionClassifier* classifier,
+    bool* ok) {
+  // For the time being, this does no rewriting at all.
+  ValidateExpression(classifier, ok);
+  return args;
+}
+
+
+ObjectLiteralProperty* Parser::RewriteNonPatternObjectLiteralProperty(
+    ObjectLiteralProperty* property, const ExpressionClassifier* classifier,
+    bool* ok) {
+  if (property != nullptr) {
+    Expression* key = RewriteNonPattern(property->key(), classifier, ok);
+    property->set_key(key);
+    Expression* value = RewriteNonPattern(property->value(), classifier, ok);
+    property->set_value(value);
+  }
+  return property;
+}
+
+
+void Parser::RewriteDestructuringAssignments() {
+  FunctionState* func = function_state_;
+  if (!allow_harmony_destructuring_assignment()) return;
+  const List<DestructuringAssignment>& assignments =
+      func->destructuring_assignments_to_rewrite();
+  for (int i = assignments.length() - 1; i >= 0; --i) {
+    // Rewrite list in reverse, so that nested assignment patterns are rewritten
+    // correctly.
+    DestructuringAssignment pair = assignments.at(i);
+    RewritableAssignmentExpression* to_rewrite =
+        pair.assignment->AsRewritableAssignmentExpression();
+    Scope* scope = pair.scope;
+    DCHECK_NOT_NULL(to_rewrite);
+    if (!to_rewrite->is_rewritten()) {
+      PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope);
+    }
+  }
+}
+
+
+void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
+  DCHECK(expr->IsRewritableAssignmentExpression());
+  parser_->function_state_->AddDestructuringAssignment(
+      Parser::DestructuringAssignment(expr, parser_->scope_));
+}
+
+
+void ParserTraits::SetFunctionNameFromPropertyName(
+    ObjectLiteralProperty* property, const AstRawString* name) {
+  Expression* value = property->value();
+  if (!value->IsFunctionLiteral() && !value->IsClassLiteral()) return;
+
+  // TODO(adamk): Support computed names.
+  if (property->is_computed_name()) return;
+  DCHECK_NOT_NULL(name);
+
+  // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
+  // of an object literal.
+  if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
+
+  if (value->IsFunctionLiteral()) {
+    auto function = value->AsFunctionLiteral();
+    if (function->is_anonymous()) {
+      if (property->kind() == ObjectLiteralProperty::GETTER) {
+        function->set_raw_name(parser_->ast_value_factory()->NewConsString(
+            parser_->ast_value_factory()->get_space_string(), name));
+      } else if (property->kind() == ObjectLiteralProperty::SETTER) {
+        function->set_raw_name(parser_->ast_value_factory()->NewConsString(
+            parser_->ast_value_factory()->set_space_string(), name));
+      } else {
+        function->set_raw_name(name);
+        DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
+      }
+    }
+  } else {
+    DCHECK(value->IsClassLiteral());
+    DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
+    auto class_literal = value->AsClassLiteral();
+    if (class_literal->raw_name() == nullptr) {
+      class_literal->set_raw_name(name);
+    }
+  }
+}
+
+
+void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
+                                                    Expression* identifier) {
+  if (!value->IsFunctionLiteral() && !value->IsClassLiteral()) return;
+  if (!identifier->IsVariableProxy()) return;
+
+  auto name = identifier->AsVariableProxy()->raw_name();
+  DCHECK_NOT_NULL(name);
+
+  if (value->IsFunctionLiteral()) {
+    auto function = value->AsFunctionLiteral();
+    if (function->is_anonymous()) {
+      function->set_raw_name(name);
+    }
+  } else {
+    DCHECK(value->IsClassLiteral());
+    auto class_literal = value->AsClassLiteral();
+    if (class_literal->raw_name() == nullptr) {
+      class_literal->set_raw_name(name);
+    }
+  }
+}
+
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/parser.h b/src/parsing/parser.h
new file mode 100644
index 0000000..7d50221
--- /dev/null
+++ b/src/parsing/parser.h
@@ -0,0 +1,1220 @@
+// 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/allocation.h"
+#include "src/ast/ast.h"
+#include "src/ast/scopes.h"
+#include "src/compiler.h"  // TODO(titzer): remove this include dependency
+#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 Target;
+
+// A container for the inputs, configuration options, and outputs of parsing.
+class ParseInfo {
+ public:
+  explicit ParseInfo(Zone* zone);
+  ParseInfo(Zone* zone, Handle<JSFunction> function);
+  ParseInfo(Zone* zone, Handle<Script> script);
+  // TODO(all) Only used via Debug::FindSharedFunctionInfoInScript, remove?
+  ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared);
+
+  ~ParseInfo() {
+    if (ast_value_factory_owned()) {
+      delete ast_value_factory_;
+      set_ast_value_factory_owned(false);
+    }
+    ast_value_factory_ = nullptr;
+  }
+
+  Zone* zone() { return zone_; }
+
+// Convenience accessor methods for flags.
+#define FLAG_ACCESSOR(flag, getter, setter)     \
+  bool getter() const { return GetFlag(flag); } \
+  void setter() { SetFlag(flag); }              \
+  void setter(bool val) { SetFlag(flag, val); }
+
+  FLAG_ACCESSOR(kToplevel, is_toplevel, set_toplevel)
+  FLAG_ACCESSOR(kLazy, is_lazy, set_lazy)
+  FLAG_ACCESSOR(kEval, is_eval, set_eval)
+  FLAG_ACCESSOR(kGlobal, is_global, set_global)
+  FLAG_ACCESSOR(kStrictMode, is_strict_mode, set_strict_mode)
+  FLAG_ACCESSOR(kStrongMode, is_strong_mode, set_strong_mode)
+  FLAG_ACCESSOR(kNative, is_native, set_native)
+  FLAG_ACCESSOR(kModule, is_module, set_module)
+  FLAG_ACCESSOR(kAllowLazyParsing, allow_lazy_parsing, set_allow_lazy_parsing)
+  FLAG_ACCESSOR(kAstValueFactoryOwned, ast_value_factory_owned,
+                set_ast_value_factory_owned)
+
+#undef FLAG_ACCESSOR
+
+  void set_parse_restriction(ParseRestriction restriction) {
+    SetFlag(kParseRestriction, restriction != NO_PARSE_RESTRICTION);
+  }
+
+  ParseRestriction parse_restriction() const {
+    return GetFlag(kParseRestriction) ? ONLY_SINGLE_FUNCTION_LITERAL
+                                      : NO_PARSE_RESTRICTION;
+  }
+
+  ScriptCompiler::ExternalSourceStream* source_stream() {
+    return source_stream_;
+  }
+  void set_source_stream(ScriptCompiler::ExternalSourceStream* source_stream) {
+    source_stream_ = source_stream;
+  }
+
+  ScriptCompiler::StreamedSource::Encoding source_stream_encoding() {
+    return source_stream_encoding_;
+  }
+  void set_source_stream_encoding(
+      ScriptCompiler::StreamedSource::Encoding source_stream_encoding) {
+    source_stream_encoding_ = source_stream_encoding;
+  }
+
+  v8::Extension* extension() { return extension_; }
+  void set_extension(v8::Extension* extension) { extension_ = extension; }
+
+  ScriptData** cached_data() { return cached_data_; }
+  void set_cached_data(ScriptData** cached_data) { cached_data_ = cached_data; }
+
+  ScriptCompiler::CompileOptions compile_options() { return compile_options_; }
+  void set_compile_options(ScriptCompiler::CompileOptions compile_options) {
+    compile_options_ = compile_options;
+  }
+
+  Scope* script_scope() { return script_scope_; }
+  void set_script_scope(Scope* script_scope) { script_scope_ = script_scope; }
+
+  AstValueFactory* ast_value_factory() { return ast_value_factory_; }
+  void set_ast_value_factory(AstValueFactory* ast_value_factory) {
+    ast_value_factory_ = ast_value_factory;
+  }
+
+  FunctionLiteral* literal() { return literal_; }
+  void set_literal(FunctionLiteral* literal) { literal_ = literal; }
+
+  Scope* scope() { return scope_; }
+  void set_scope(Scope* scope) { scope_ = scope; }
+
+  UnicodeCache* unicode_cache() { return unicode_cache_; }
+  void set_unicode_cache(UnicodeCache* unicode_cache) {
+    unicode_cache_ = unicode_cache;
+  }
+
+  uintptr_t stack_limit() { return stack_limit_; }
+  void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
+
+  uint32_t hash_seed() { return hash_seed_; }
+  void set_hash_seed(uint32_t hash_seed) { hash_seed_ = hash_seed; }
+
+  //--------------------------------------------------------------------------
+  // TODO(titzer): these should not be part of ParseInfo.
+  //--------------------------------------------------------------------------
+  Isolate* isolate() { return isolate_; }
+  Handle<JSFunction> closure() { return closure_; }
+  Handle<SharedFunctionInfo> shared_info() { return shared_; }
+  Handle<Script> script() { return script_; }
+  Handle<Context> context() { return context_; }
+  void clear_script() { script_ = Handle<Script>::null(); }
+  void set_isolate(Isolate* isolate) { isolate_ = isolate; }
+  void set_context(Handle<Context> context) { context_ = context; }
+  void set_script(Handle<Script> script) { script_ = script; }
+  //--------------------------------------------------------------------------
+
+  LanguageMode language_mode() {
+    return construct_language_mode(is_strict_mode(), is_strong_mode());
+  }
+  void set_language_mode(LanguageMode language_mode) {
+    STATIC_ASSERT(LANGUAGE_END == 3);
+    set_strict_mode(language_mode & STRICT_BIT);
+    set_strong_mode(language_mode & STRONG_BIT);
+  }
+
+  void ReopenHandlesInNewHandleScope() {
+    closure_ = Handle<JSFunction>(*closure_);
+    shared_ = Handle<SharedFunctionInfo>(*shared_);
+    script_ = Handle<Script>(*script_);
+    context_ = Handle<Context>(*context_);
+  }
+
+#ifdef DEBUG
+  bool script_is_native() { return script_->type() == Script::TYPE_NATIVE; }
+#endif  // DEBUG
+
+ private:
+  // Various configuration flags for parsing.
+  enum Flag {
+    // ---------- Input flags ---------------------------
+    kToplevel = 1 << 0,
+    kLazy = 1 << 1,
+    kEval = 1 << 2,
+    kGlobal = 1 << 3,
+    kStrictMode = 1 << 4,
+    kStrongMode = 1 << 5,
+    kNative = 1 << 6,
+    kParseRestriction = 1 << 7,
+    kModule = 1 << 8,
+    kAllowLazyParsing = 1 << 9,
+    // ---------- Output flags --------------------------
+    kAstValueFactoryOwned = 1 << 10
+  };
+
+  //------------- Inputs to parsing and scope analysis -----------------------
+  Zone* zone_;
+  unsigned flags_;
+  ScriptCompiler::ExternalSourceStream* source_stream_;
+  ScriptCompiler::StreamedSource::Encoding source_stream_encoding_;
+  v8::Extension* extension_;
+  ScriptCompiler::CompileOptions compile_options_;
+  Scope* script_scope_;
+  UnicodeCache* unicode_cache_;
+  uintptr_t stack_limit_;
+  uint32_t hash_seed_;
+
+  // TODO(titzer): Move handles and isolate out of ParseInfo.
+  Isolate* isolate_;
+  Handle<JSFunction> closure_;
+  Handle<SharedFunctionInfo> shared_;
+  Handle<Script> script_;
+  Handle<Context> context_;
+
+  //----------- Inputs+Outputs of parsing and scope analysis -----------------
+  ScriptData** cached_data_;  // used if available, populated if requested.
+  AstValueFactory* ast_value_factory_;  // used if available, otherwise new.
+
+  //----------- Outputs of parsing and scope analysis ------------------------
+  FunctionLiteral* literal_;  // produced by full parser.
+  Scope* scope_;              // produced by scope analysis.
+
+  void SetFlag(Flag f) { flags_ |= f; }
+  void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; }
+  bool GetFlag(Flag f) const { return (flags_ & f) != 0; }
+
+  void set_shared_info(Handle<SharedFunctionInfo> shared) { shared_ = shared; }
+  void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
+};
+
+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(Scope* 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]; }
+};
+
+
+class ParserTraits {
+ public:
+  struct Type {
+    // TODO(marja): To be removed. The Traits object should contain all the data
+    // it needs.
+    typedef v8::internal::Parser* Parser;
+
+    typedef Variable GeneratorVariable;
+
+    typedef v8::internal::AstProperties AstProperties;
+
+    // Return types for traversing functions.
+    typedef const AstRawString* Identifier;
+    typedef v8::internal::Expression* Expression;
+    typedef Yield* YieldExpression;
+    typedef v8::internal::FunctionLiteral* FunctionLiteral;
+    typedef v8::internal::ClassLiteral* ClassLiteral;
+    typedef v8::internal::Literal* Literal;
+    typedef ObjectLiteral::Property* ObjectLiteralProperty;
+    typedef ZoneList<v8::internal::Expression*>* ExpressionList;
+    typedef ZoneList<ObjectLiteral::Property*>* PropertyList;
+    typedef ParserFormalParameters::Parameter FormalParameter;
+    typedef ParserFormalParameters FormalParameters;
+    typedef ZoneList<v8::internal::Statement*>* StatementList;
+
+    // For constructing objects returned by the traversing functions.
+    typedef AstNodeFactory Factory;
+  };
+
+  explicit ParserTraits(Parser* parser) : parser_(parser) {}
+
+  // Helper functions for recursive descent.
+  bool IsEval(const AstRawString* identifier) const;
+  bool IsArguments(const AstRawString* identifier) const;
+  bool IsEvalOrArguments(const AstRawString* identifier) const;
+  bool IsUndefined(const AstRawString* identifier) const;
+  V8_INLINE bool IsFutureStrictReserved(const AstRawString* identifier) const;
+
+  // Returns true if the expression is of type "this.foo".
+  static bool IsThisProperty(Expression* expression);
+
+  static bool IsIdentifier(Expression* expression);
+
+  bool IsPrototype(const AstRawString* identifier) const;
+
+  bool IsConstructor(const AstRawString* identifier) const;
+
+  static const AstRawString* AsIdentifier(Expression* expression) {
+    DCHECK(IsIdentifier(expression));
+    return expression->AsVariableProxy()->raw_name();
+  }
+
+  static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
+    return ObjectLiteral::IsBoilerplateProperty(property);
+  }
+
+  static bool IsArrayIndex(const AstRawString* string, uint32_t* index) {
+    return string->AsArrayIndex(index);
+  }
+
+  static Expression* GetPropertyValue(ObjectLiteral::Property* property) {
+    return property->value();
+  }
+
+  // Functions for encapsulating the differences between parsing and preparsing;
+  // operations interleaved with the recursive descent.
+  static void PushLiteralName(FuncNameInferrer* fni, const AstRawString* id) {
+    fni->PushLiteralName(id);
+  }
+
+  void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
+
+  static void InferFunctionName(FuncNameInferrer* fni,
+                                FunctionLiteral* func_to_infer) {
+    fni->AddFunction(func_to_infer);
+  }
+
+  static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+      Scope* scope, ObjectLiteralProperty* property, bool* has_function) {
+    Expression* value = property->value();
+    if (scope->DeclarationScope()->is_script_scope() &&
+        value->AsFunctionLiteral() != NULL) {
+      *has_function = true;
+      value->AsFunctionLiteral()->set_pretenure();
+    }
+  }
+
+  // If we assign a function literal to a property we pretenure the
+  // literal so it can be added as a constant function property.
+  static void CheckAssigningFunctionLiteralToProperty(Expression* left,
+                                                      Expression* right);
+
+  // Determine if the expression is a variable proxy and mark it as being used
+  // in an assignment or with a increment/decrement operator.
+  static Expression* MarkExpressionAsAssigned(Expression* 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,
+                                              AstNodeFactory* factory);
+
+  // 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, AstNodeFactory* factory);
+
+  // Generate AST node that throws a ReferenceError with the given type.
+  Expression* NewThrowReferenceError(MessageTemplate::Template message,
+                                     int 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.
+  Expression* NewThrowSyntaxError(MessageTemplate::Template message,
+                                  const AstRawString* arg, int pos);
+
+  // Generate AST node that throws a TypeError with the given
+  // type. Both arguments must be non-null (in the handle sense).
+  Expression* NewThrowTypeError(MessageTemplate::Template message,
+                                const AstRawString* arg, int pos);
+
+  // Generic AST generator for throwing errors from compiled code.
+  Expression* NewThrowError(Runtime::FunctionId function_id,
+                            MessageTemplate::Template message,
+                            const AstRawString* arg, int pos);
+
+  // Reporting errors.
+  void ReportMessageAt(Scanner::Location source_location,
+                       MessageTemplate::Template message,
+                       const char* arg = NULL,
+                       ParseErrorType error_type = kSyntaxError);
+  void ReportMessage(MessageTemplate::Template message, const char* arg = NULL,
+                     ParseErrorType error_type = kSyntaxError);
+  void ReportMessage(MessageTemplate::Template message, const AstRawString* arg,
+                     ParseErrorType error_type = kSyntaxError);
+  void ReportMessageAt(Scanner::Location source_location,
+                       MessageTemplate::Template message,
+                       const AstRawString* arg,
+                       ParseErrorType error_type = kSyntaxError);
+
+  // "null" return type creators.
+  static const AstRawString* EmptyIdentifier() {
+    return NULL;
+  }
+  static Expression* EmptyExpression() {
+    return NULL;
+  }
+  static Literal* EmptyLiteral() {
+    return NULL;
+  }
+  static ObjectLiteralProperty* EmptyObjectLiteralProperty() { return NULL; }
+  static FunctionLiteral* EmptyFunctionLiteral() { return NULL; }
+
+  // Used in error return values.
+  static ZoneList<Expression*>* NullExpressionList() {
+    return NULL;
+  }
+  static const AstRawString* EmptyFormalParameter() { return NULL; }
+
+  // Non-NULL empty string.
+  V8_INLINE const AstRawString* EmptyIdentifierString();
+
+  // Odd-ball literal creators.
+  Literal* GetLiteralTheHole(int position, AstNodeFactory* factory);
+
+  // Producing data during the recursive descent.
+  const AstRawString* GetSymbol(Scanner* scanner);
+  const AstRawString* GetNextSymbol(Scanner* scanner);
+  const AstRawString* GetNumberAsSymbol(Scanner* scanner);
+
+  Expression* ThisExpression(Scope* scope, AstNodeFactory* factory,
+                             int pos = RelocInfo::kNoPosition);
+  Expression* SuperPropertyReference(Scope* scope, AstNodeFactory* factory,
+                                     int pos);
+  Expression* SuperCallReference(Scope* scope, AstNodeFactory* factory,
+                                 int pos);
+  Expression* NewTargetExpression(Scope* scope, AstNodeFactory* factory,
+                                  int pos);
+  Expression* DefaultConstructor(bool call_super, Scope* scope, int pos,
+                                 int end_pos, LanguageMode language_mode);
+  Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,
+                                 AstNodeFactory* factory);
+  Expression* ExpressionFromIdentifier(const AstRawString* name,
+                                       int start_position, int end_position,
+                                       Scope* scope, AstNodeFactory* factory);
+  Expression* ExpressionFromString(int pos, Scanner* scanner,
+                                   AstNodeFactory* factory);
+  Expression* GetIterator(Expression* iterable, AstNodeFactory* factory,
+                          int pos);
+  ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
+    return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
+  }
+  ZoneList<ObjectLiteral::Property*>* NewPropertyList(int size, Zone* zone) {
+    return new(zone) ZoneList<ObjectLiteral::Property*>(size, zone);
+  }
+  ZoneList<v8::internal::Statement*>* NewStatementList(int size, Zone* zone) {
+    return new(zone) ZoneList<v8::internal::Statement*>(size, zone);
+  }
+
+  V8_INLINE void AddParameterInitializationBlock(
+      const ParserFormalParameters& parameters,
+      ZoneList<v8::internal::Statement*>* body, bool* ok);
+
+  V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type,
+                            FunctionKind kind = kNormalFunction);
+
+  V8_INLINE void AddFormalParameter(ParserFormalParameters* parameters,
+                                    Expression* pattern,
+                                    Expression* initializer,
+                                    int initializer_end_position, bool is_rest);
+  V8_INLINE void DeclareFormalParameter(
+      Scope* scope, const ParserFormalParameters::Parameter& parameter,
+      ExpressionClassifier* classifier);
+  void ParseArrowFunctionFormalParameters(ParserFormalParameters* parameters,
+                                          Expression* params,
+                                          const Scanner::Location& params_loc,
+                                          bool* ok);
+  void ParseArrowFunctionFormalParameterList(
+      ParserFormalParameters* parameters, Expression* params,
+      const Scanner::Location& params_loc,
+      Scanner::Location* duplicate_loc, bool* ok);
+
+  V8_INLINE DoExpression* ParseDoExpression(bool* ok);
+
+  void ReindexLiterals(const ParserFormalParameters& parameters);
+
+  // Temporary glue; these functions will move to ParserBase.
+  Expression* ParseV8Intrinsic(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,
+      FunctionLiteral::ArityRestriction arity_restriction,
+      LanguageMode language_mode, bool* ok);
+  V8_INLINE void SkipLazyFunctionBody(
+      int* materialized_literal_count, int* expected_property_count, bool* ok,
+      Scanner::BookmarkScope* bookmark = nullptr);
+  V8_INLINE ZoneList<Statement*>* ParseEagerFunctionBody(
+      const AstRawString* name, int pos,
+      const ParserFormalParameters& parameters, FunctionKind kind,
+      FunctionLiteral::FunctionType function_type, bool* ok);
+
+  ClassLiteral* ParseClassLiteral(const AstRawString* name,
+                                  Scanner::Location class_name_location,
+                                  bool name_is_strict_reserved, int pos,
+                                  bool* ok);
+
+  V8_INLINE void CheckConflictingVarDeclarations(v8::internal::Scope* scope,
+                                                 bool* ok);
+
+  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;
+
+  V8_INLINE TemplateLiteralState OpenTemplateLiteral(int pos);
+  V8_INLINE void AddTemplateSpan(TemplateLiteralState* state, bool tail);
+  V8_INLINE void AddTemplateExpression(TemplateLiteralState* state,
+                                       Expression* expression);
+  V8_INLINE Expression* CloseTemplateLiteral(TemplateLiteralState* state,
+                                             int start, Expression* tag);
+  V8_INLINE Expression* NoTemplateTag() { return NULL; }
+  V8_INLINE static bool IsTaggedTemplate(const Expression* tag) {
+    return tag != NULL;
+  }
+
+  V8_INLINE ZoneList<v8::internal::Expression*>* PrepareSpreadArguments(
+      ZoneList<v8::internal::Expression*>* list);
+  V8_INLINE void MaterializeUnspreadArgumentsLiterals(int count) {}
+  V8_INLINE Expression* SpreadCall(Expression* function,
+                                   ZoneList<v8::internal::Expression*>* args,
+                                   int pos);
+  V8_INLINE Expression* SpreadCallNew(Expression* function,
+                                      ZoneList<v8::internal::Expression*>* args,
+                                      int pos);
+
+  // Rewrite all DestructuringAssignments in the current FunctionState.
+  V8_INLINE void RewriteDestructuringAssignments();
+
+  V8_INLINE void QueueDestructuringAssignmentForRewriting(
+      Expression* assignment);
+
+  void SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
+                                       const AstRawString* name);
+
+  void SetFunctionNameFromIdentifierRef(Expression* value,
+                                        Expression* identifier);
+
+  // Rewrite expressions that are not used as patterns
+  V8_INLINE Expression* RewriteNonPattern(
+      Expression* expr, const ExpressionClassifier* classifier, bool* ok);
+  V8_INLINE ZoneList<Expression*>* RewriteNonPatternArguments(
+      ZoneList<Expression*>* args, const ExpressionClassifier* classifier,
+      bool* ok);
+  V8_INLINE ObjectLiteralProperty* RewriteNonPatternObjectLiteralProperty(
+      ObjectLiteralProperty* property, const ExpressionClassifier* classifier,
+      bool* ok);
+
+ private:
+  Parser* parser_;
+};
+
+
+class Parser : public ParserBase<ParserTraits> {
+ 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);
+
+  // 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 ParserTraits;
+
+  // 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* ParseLazy(Isolate* isolate, ParseInfo* info,
+                             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;
+  }
+
+  // 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.
+  void* ParseStatementList(ZoneList<Statement*>* body, int end_token, bool* ok);
+  Statement* ParseStatementListItem(bool* ok);
+  void* ParseModuleItemList(ZoneList<Statement*>* body, bool* ok);
+  Statement* ParseModuleItem(bool* ok);
+  const AstRawString* ParseModuleSpecifier(bool* ok);
+  Statement* 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);
+  ZoneList<ImportDeclaration*>* ParseNamedImports(int pos, bool* ok);
+  Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+  Statement* ParseSubStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+  Statement* ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels,
+                                   bool* ok);
+  Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
+                                      bool* ok);
+  Statement* ParseClassDeclaration(ZoneList<const AstRawString*>* names,
+                                   bool* ok);
+  Statement* ParseNativeDeclaration(bool* ok);
+  Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
+  Block* ParseBlock(ZoneList<const AstRawString*>* labels,
+                    bool finalize_block_scope, bool* ok);
+  Block* ParseVariableStatement(VariableDeclarationContext var_context,
+                                ZoneList<const AstRawString*>* names,
+                                bool* ok);
+  DoExpression* ParseDoExpression(bool* ok);
+
+  struct DeclarationDescriptor {
+    enum Kind { NORMAL, PARAMETER };
+    Parser* parser;
+    Scope* scope;
+    Scope* hoist_scope;
+    VariableMode mode;
+    bool needs_init;
+    int declaration_pos;
+    int initialization_pos;
+    Kind declaration_kind;
+  };
+
+  struct DeclarationParsingResult {
+    struct Declaration {
+      Declaration(Expression* pattern, int initializer_position,
+                  Expression* initializer)
+          : pattern(pattern),
+            initializer_position(initializer_position),
+            initializer(initializer) {}
+
+      Expression* pattern;
+      int initializer_position;
+      Expression* initializer;
+    };
+
+    DeclarationParsingResult()
+        : declarations(4),
+          first_initializer_loc(Scanner::Location::invalid()),
+          bindings_loc(Scanner::Location::invalid()) {}
+
+    Block* BuildInitializationBlock(ZoneList<const AstRawString*>* names,
+                                    bool* ok);
+
+    DeclarationDescriptor descriptor;
+    List<Declaration> declarations;
+    Scanner::Location first_initializer_loc;
+    Scanner::Location bindings_loc;
+  };
+
+  class PatternRewriter : private AstVisitor {
+   public:
+    static void DeclareAndInitializeVariables(
+        Block* block, const DeclarationDescriptor* declaration_descriptor,
+        const DeclarationParsingResult::Declaration* declaration,
+        ZoneList<const AstRawString*>* names, bool* ok);
+
+    static void RewriteDestructuringAssignment(
+        Parser* parser, RewritableAssignmentExpression* expr, Scope* Scope);
+
+    static Expression* RewriteDestructuringAssignment(Parser* parser,
+                                                      Assignment* assignment,
+                                                      Scope* scope);
+
+    void set_initializer_position(int pos) { initializer_position_ = pos; }
+
+   private:
+    PatternRewriter() {}
+
+#define DECLARE_VISIT(type) void Visit##type(v8::internal::type* node) override;
+    // Visiting functions for AST nodes make this an AstVisitor.
+    AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+    void Visit(AstNode* node) override;
+
+    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_++;
+      pattern->Accept(this);
+      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);
+
+    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_;
+  };
+
+
+  void ParseVariableDeclarations(VariableDeclarationContext var_context,
+                                 DeclarationParsingResult* parsing_result,
+                                 bool* ok);
+  Statement* ParseExpressionOrLabelledStatement(
+      ZoneList<const AstRawString*>* labels, bool* ok);
+  IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
+                                bool* ok);
+  Statement* ParseContinueStatement(bool* ok);
+  Statement* ParseBreakStatement(ZoneList<const AstRawString*>* labels,
+                                 bool* ok);
+  Statement* ParseReturnStatement(bool* ok);
+  Statement* ParseWithStatement(ZoneList<const AstRawString*>* labels,
+                                bool* ok);
+  CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
+  Statement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
+                                  bool* ok);
+  DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
+                                          bool* ok);
+  WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
+                                      bool* ok);
+  Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+  Statement* ParseThrowStatement(bool* ok);
+  Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
+  TryStatement* ParseTryStatement(bool* ok);
+  DebuggerStatement* ParseDebuggerStatement(bool* ok);
+
+  // !%_IsJSReceiver(result = iterator.next()) &&
+  //     %ThrowIteratorResultNotAnObject(result)
+  Expression* BuildIteratorNextResult(Expression* iterator, Variable* result,
+                                      int pos);
+
+
+  // Initialize the components of a for-in / for-of statement.
+  void InitializeForEachStatement(ForEachStatement* stmt, Expression* each,
+                                  Expression* subject, Statement* body,
+                                  bool is_destructuring);
+  Statement* DesugarLexicalBindingsInForStatement(
+      Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names,
+      ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+      Statement* body, bool* ok);
+
+  void RewriteDoExpression(Expression* expr, 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,
+      FunctionLiteral::ArityRestriction arity_restriction,
+      LanguageMode language_mode, bool* ok);
+
+
+  ClassLiteral* ParseClassLiteral(const AstRawString* name,
+                                  Scanner::Location class_name_location,
+                                  bool name_is_strict_reserved, int pos,
+                                  bool* ok);
+
+  // Magical syntax support.
+  Expression* ParseV8Intrinsic(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(Scope* scope, bool* ok);
+
+  // Parser support
+  VariableProxy* NewUnresolved(const AstRawString* name, VariableMode mode);
+  Variable* Declare(Declaration* declaration,
+                    DeclarationDescriptor::Kind declaration_kind, bool resolve,
+                    bool* ok, Scope* declaration_scope = nullptr);
+
+  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(bool call_super, Scope* scope, 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 bookmark is set, the (pre-)parser may decide to abort skipping
+  // in order to force the function to be eagerly parsed, after all.
+  // In this case, it'll reset the scanner using the bookmark.
+  void SkipLazyFunctionBody(int* materialized_literal_count,
+                            int* expected_property_count, bool* ok,
+                            Scanner::BookmarkScope* bookmark = nullptr);
+
+  PreParser::PreParseResult ParseLazyFunctionBodyWithPreParser(
+      SingletonLogger* logger, Scanner::BookmarkScope* bookmark = nullptr);
+
+  Block* BuildParameterInitializationBlock(
+      const ParserFormalParameters& parameters, 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);
+
+  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);
+
+  ZoneList<v8::internal::Expression*>* PrepareSpreadArguments(
+      ZoneList<v8::internal::Expression*>* list);
+  Expression* SpreadCall(Expression* function,
+                         ZoneList<v8::internal::Expression*>* args, int pos);
+  Expression* SpreadCallNew(Expression* function,
+                            ZoneList<v8::internal::Expression*>* args, int pos);
+
+  void SetLanguageMode(Scope* scope, LanguageMode mode);
+  void RaiseLanguageMode(LanguageMode mode);
+
+  V8_INLINE void RewriteDestructuringAssignments();
+
+  V8_INLINE Expression* RewriteNonPattern(
+      Expression* expr, const ExpressionClassifier* classifier, bool* ok);
+  V8_INLINE ZoneList<Expression*>* RewriteNonPatternArguments(
+      ZoneList<Expression*>* args, const ExpressionClassifier* classifier,
+      bool* ok);
+  V8_INLINE ObjectLiteralProperty* RewriteNonPatternObjectLiteralProperty(
+      ObjectLiteralProperty* property, const ExpressionClassifier* classifier,
+      bool* ok);
+
+  friend class InitializerRewriter;
+  void RewriteParameterInitializer(Expression* expr, Scope* scope);
+
+  Scanner scanner_;
+  PreParser* reusable_preparser_;
+  Scope* original_scope_;  // for ES5 function declarations in sloppy eval
+  Target* 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_;
+};
+
+
+bool ParserTraits::IsFutureStrictReserved(
+    const AstRawString* identifier) const {
+  return parser_->scanner()->IdentifierIsFutureStrictReserved(identifier);
+}
+
+
+Scope* ParserTraits::NewScope(Scope* parent_scope, ScopeType scope_type,
+                              FunctionKind kind) {
+  return parser_->NewScope(parent_scope, scope_type, kind);
+}
+
+
+const AstRawString* ParserTraits::EmptyIdentifierString() {
+  return parser_->ast_value_factory()->empty_string();
+}
+
+
+void ParserTraits::SkipLazyFunctionBody(int* materialized_literal_count,
+                                        int* expected_property_count, bool* ok,
+                                        Scanner::BookmarkScope* bookmark) {
+  return parser_->SkipLazyFunctionBody(materialized_literal_count,
+                                       expected_property_count, ok, bookmark);
+}
+
+
+ZoneList<Statement*>* ParserTraits::ParseEagerFunctionBody(
+    const AstRawString* name, int pos, const ParserFormalParameters& parameters,
+    FunctionKind kind, FunctionLiteral::FunctionType function_type, bool* ok) {
+  return parser_->ParseEagerFunctionBody(name, pos, parameters, kind,
+                                         function_type, ok);
+}
+
+
+void ParserTraits::CheckConflictingVarDeclarations(v8::internal::Scope* scope,
+                                                   bool* ok) {
+  parser_->CheckConflictingVarDeclarations(scope, ok);
+}
+
+
+// Support for handling complex values (array and object literals) that
+// can be fully handled at compile time.
+class CompileTimeValue: public AllStatic {
+ public:
+  enum LiteralType {
+    OBJECT_LITERAL_FAST_ELEMENTS,
+    OBJECT_LITERAL_SLOW_ELEMENTS,
+    ARRAY_LITERAL
+  };
+
+  static bool IsCompileTimeValue(Expression* expression);
+
+  // Get the value as a compile time value.
+  static Handle<FixedArray> GetValue(Isolate* isolate, Expression* expression);
+
+  // Get the type of a compile time value returned by GetValue().
+  static LiteralType GetLiteralType(Handle<FixedArray> value);
+
+  // Get the elements array of a compile time value returned by GetValue().
+  static Handle<FixedArray> GetElements(Handle<FixedArray> value);
+
+ private:
+  static const int kLiteralTypeSlot = 0;
+  static const int kElementsSlot = 1;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompileTimeValue);
+};
+
+
+ParserTraits::TemplateLiteralState ParserTraits::OpenTemplateLiteral(int pos) {
+  return parser_->OpenTemplateLiteral(pos);
+}
+
+
+void ParserTraits::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
+  parser_->AddTemplateSpan(state, tail);
+}
+
+
+void ParserTraits::AddTemplateExpression(TemplateLiteralState* state,
+                                         Expression* expression) {
+  parser_->AddTemplateExpression(state, expression);
+}
+
+
+Expression* ParserTraits::CloseTemplateLiteral(TemplateLiteralState* state,
+                                               int start, Expression* tag) {
+  return parser_->CloseTemplateLiteral(state, start, tag);
+}
+
+
+ZoneList<v8::internal::Expression*>* ParserTraits::PrepareSpreadArguments(
+    ZoneList<v8::internal::Expression*>* list) {
+  return parser_->PrepareSpreadArguments(list);
+}
+
+
+Expression* ParserTraits::SpreadCall(Expression* function,
+                                     ZoneList<v8::internal::Expression*>* args,
+                                     int pos) {
+  return parser_->SpreadCall(function, args, pos);
+}
+
+
+Expression* ParserTraits::SpreadCallNew(
+    Expression* function, ZoneList<v8::internal::Expression*>* args, int pos) {
+  return parser_->SpreadCallNew(function, args, pos);
+}
+
+
+void ParserTraits::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()
+                                 : parser_->ast_value_factory()->empty_string();
+  parameters->params.Add(
+      ParserFormalParameters::Parameter(name, pattern, initializer,
+                                        initializer_end_position, is_rest),
+      parameters->scope->zone());
+}
+
+
+void ParserTraits::DeclareFormalParameter(
+    Scope* scope, const ParserFormalParameters::Parameter& parameter,
+    ExpressionClassifier* classifier) {
+  bool is_duplicate = false;
+  bool is_simple = classifier->is_simple_parameter_list();
+  auto name = is_simple || parameter.is_rest
+                  ? parameter.name
+                  : parser_->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);
+  if (is_duplicate) {
+    classifier->RecordDuplicateFormalParameterError(
+        parser_->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 ParserTraits::AddParameterInitializationBlock(
+    const ParserFormalParameters& parameters,
+    ZoneList<v8::internal::Statement*>* body, bool* ok) {
+  if (!parameters.is_simple) {
+    auto* init_block =
+        parser_->BuildParameterInitializationBlock(parameters, ok);
+    if (!*ok) return;
+    if (init_block != nullptr) {
+      body->Add(init_block, parser_->zone());
+    }
+  }
+}
+
+
+DoExpression* ParserTraits::ParseDoExpression(bool* ok) {
+  return parser_->ParseDoExpression(ok);
+}
+
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_PARSER_H_
diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc
new file mode 100644
index 0000000..6e20282
--- /dev/null
+++ b/src/parsing/pattern-rewriter.cc
@@ -0,0 +1,628 @@
+// Copyright 2015 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.
+
+#include "src/ast/ast.h"
+#include "src/messages.h"
+#include "src/parsing/parameter-initializer-rewriter.h"
+#include "src/parsing/parser.h"
+
+namespace v8 {
+
+namespace internal {
+
+void Parser::PatternRewriter::DeclareAndInitializeVariables(
+    Block* block, const DeclarationDescriptor* declaration_descriptor,
+    const DeclarationParsingResult::Declaration* declaration,
+    ZoneList<const AstRawString*>* names, bool* ok) {
+  PatternRewriter rewriter;
+
+  rewriter.scope_ = declaration_descriptor->scope;
+  rewriter.parser_ = declaration_descriptor->parser;
+  rewriter.context_ = BINDING;
+  rewriter.pattern_ = declaration->pattern;
+  rewriter.initializer_position_ = declaration->initializer_position;
+  rewriter.block_ = block;
+  rewriter.descriptor_ = declaration_descriptor;
+  rewriter.names_ = names;
+  rewriter.ok_ = ok;
+  rewriter.recursion_level_ = 0;
+
+  rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer);
+}
+
+
+void Parser::PatternRewriter::RewriteDestructuringAssignment(
+    Parser* parser, RewritableAssignmentExpression* to_rewrite, Scope* scope) {
+  PatternRewriter rewriter;
+
+  DCHECK(!to_rewrite->is_rewritten());
+
+  bool ok = true;
+  rewriter.scope_ = scope;
+  rewriter.parser_ = parser;
+  rewriter.context_ = ASSIGNMENT;
+  rewriter.pattern_ = to_rewrite;
+  rewriter.block_ = nullptr;
+  rewriter.descriptor_ = nullptr;
+  rewriter.names_ = nullptr;
+  rewriter.ok_ = &ok;
+  rewriter.recursion_level_ = 0;
+
+  rewriter.RecurseIntoSubpattern(rewriter.pattern_, nullptr);
+  DCHECK(ok);
+}
+
+
+Expression* Parser::PatternRewriter::RewriteDestructuringAssignment(
+    Parser* parser, Assignment* assignment, Scope* scope) {
+  DCHECK_NOT_NULL(assignment);
+  DCHECK_EQ(Token::ASSIGN, assignment->op());
+  auto to_rewrite =
+      parser->factory()->NewRewritableAssignmentExpression(assignment);
+  RewriteDestructuringAssignment(parser, to_rewrite, scope);
+  return to_rewrite->expression();
+}
+
+
+bool Parser::PatternRewriter::IsAssignmentContext(PatternContext c) const {
+  return c == ASSIGNMENT || c == ASSIGNMENT_INITIALIZER;
+}
+
+
+bool Parser::PatternRewriter::IsBindingContext(PatternContext c) const {
+  return c == BINDING || c == INITIALIZER;
+}
+
+
+Parser::PatternRewriter::PatternContext
+Parser::PatternRewriter::SetAssignmentContextIfNeeded(Expression* node) {
+  PatternContext old_context = context();
+  if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN) {
+    set_context(ASSIGNMENT);
+  }
+  return old_context;
+}
+
+
+Parser::PatternRewriter::PatternContext
+Parser::PatternRewriter::SetInitializerContextIfNeeded(Expression* node) {
+  // Set appropriate initializer context for BindingElement and
+  // AssignmentElement nodes
+  PatternContext old_context = context();
+  bool is_destructuring_assignment =
+      node->IsRewritableAssignmentExpression() &&
+      !node->AsRewritableAssignmentExpression()->is_rewritten();
+  bool is_assignment =
+      node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN;
+  if (is_destructuring_assignment || is_assignment) {
+    switch (old_context) {
+      case BINDING:
+        set_context(INITIALIZER);
+        break;
+      case ASSIGNMENT:
+        set_context(ASSIGNMENT_INITIALIZER);
+        break;
+      default:
+        break;
+    }
+  }
+  return old_context;
+}
+
+
+void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
+  Expression* value = current_value_;
+
+  if (IsAssignmentContext()) {
+    // In an assignment context, simply perform the assignment
+    Assignment* assignment = factory()->NewAssignment(
+        Token::ASSIGN, pattern, value, pattern->position());
+    block_->statements()->Add(
+        factory()->NewExpressionStatement(assignment, pattern->position()),
+        zone());
+    return;
+  }
+
+  descriptor_->scope->RemoveUnresolved(pattern);
+
+  // Declare variable.
+  // Note that we *always* must treat the initial value via a separate init
+  // assignment for variables and constants because the value must be assigned
+  // when the variable is encountered in the source. But the variable/constant
+  // is declared (and set to 'undefined') upon entering the function within
+  // which the variable or constant is declared. Only function variables have
+  // an initial value in the declaration (because they are initialized upon
+  // entering the function).
+  //
+  // If we have a legacy const declaration, in an inner scope, the proxy
+  // is always bound to the declared variable (independent of possibly
+  // surrounding 'with' statements).
+  // For let/const declarations in harmony mode, we can also immediately
+  // pre-resolve the proxy because it resides in the same scope as the
+  // declaration.
+  const AstRawString* name = pattern->raw_name();
+  VariableProxy* proxy = parser_->NewUnresolved(name, descriptor_->mode);
+  Declaration* declaration = factory()->NewVariableDeclaration(
+      proxy, descriptor_->mode, descriptor_->scope,
+      descriptor_->declaration_pos);
+  Variable* var =
+      parser_->Declare(declaration, descriptor_->declaration_kind,
+                       descriptor_->mode != VAR, ok_, descriptor_->hoist_scope);
+  if (!*ok_) return;
+  DCHECK_NOT_NULL(var);
+  DCHECK(!proxy->is_resolved() || proxy->var() == var);
+  var->set_initializer_position(initializer_position_);
+
+  DCHECK(initializer_position_ != RelocInfo::kNoPosition);
+
+  Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode)
+                                 ? descriptor_->scope
+                                 : descriptor_->scope->DeclarationScope();
+  if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
+    parser_->ReportMessage(MessageTemplate::kTooManyVariables);
+    *ok_ = false;
+    return;
+  }
+  if (names_) {
+    names_->Add(name, zone());
+  }
+
+  // Initialize variables if needed. A
+  // declaration of the form:
+  //
+  //    var v = x;
+  //
+  // is syntactic sugar for:
+  //
+  //    var v; v = x;
+  //
+  // In particular, we need to re-lookup 'v' (in scope_, not
+  // declaration_scope) as it may be a different 'v' than the 'v' in the
+  // declaration (e.g., if we are inside a 'with' statement or 'catch'
+  // block).
+  //
+  // However, note that const declarations are different! A const
+  // declaration of the form:
+  //
+  //   const c = x;
+  //
+  // is *not* syntactic sugar for:
+  //
+  //   const c; c = x;
+  //
+  // The "variable" c initialized to x is the same as the declared
+  // one - there is no re-lookup (see the last parameter of the
+  // Declare() call above).
+  Scope* initialization_scope = IsImmutableVariableMode(descriptor_->mode)
+                                    ? declaration_scope
+                                    : descriptor_->scope;
+
+
+  // Global variable declarations must be compiled in a specific
+  // way. When the script containing the global variable declaration
+  // is entered, the global variable must be declared, so that if it
+  // doesn't exist (on the global object itself, see ES5 errata) it
+  // gets created with an initial undefined value. This is handled
+  // by the declarations part of the function representing the
+  // top-level global code; see Runtime::DeclareGlobalVariable. If
+  // it already exists (in the object or in a prototype), it is
+  // *not* touched until the variable declaration statement is
+  // executed.
+  //
+  // Executing the variable declaration statement will always
+  // guarantee to give the global object an own property.
+  // This way, global variable declarations can shadow
+  // properties in the prototype chain, but only after the variable
+  // declaration statement has been executed. This is important in
+  // browsers where the global object (window) has lots of
+  // properties defined in prototype objects.
+  if (initialization_scope->is_script_scope() &&
+      !IsLexicalVariableMode(descriptor_->mode)) {
+    // Compute the arguments for the runtime
+    // call.test-parsing/InitializedDeclarationsInStrictForOfError
+    ZoneList<Expression*>* arguments =
+        new (zone()) ZoneList<Expression*>(3, zone());
+    // We have at least 1 parameter.
+    arguments->Add(
+        factory()->NewStringLiteral(name, descriptor_->declaration_pos),
+        zone());
+    CallRuntime* initialize;
+
+    if (IsImmutableVariableMode(descriptor_->mode)) {
+      arguments->Add(value, zone());
+      value = NULL;  // zap the value to avoid the unnecessary assignment
+
+      // Construct the call to Runtime_InitializeConstGlobal
+      // and add it to the initialization statement block.
+      // Note that the function does different things depending on
+      // the number of arguments (1 or 2).
+      initialize =
+          factory()->NewCallRuntime(Runtime::kInitializeConstGlobal, arguments,
+                                    descriptor_->initialization_pos);
+    } else {
+      // Add language mode.
+      // We may want to pass singleton to avoid Literal allocations.
+      LanguageMode language_mode = initialization_scope->language_mode();
+      arguments->Add(factory()->NewNumberLiteral(language_mode,
+                                                 descriptor_->declaration_pos),
+                     zone());
+
+      // Be careful not to assign a value to the global variable if
+      // we're in a with. The initialization value should not
+      // necessarily be stored in the global object in that case,
+      // which is why we need to generate a separate assignment node.
+      if (value != NULL && !descriptor_->scope->inside_with()) {
+        arguments->Add(value, zone());
+        value = NULL;  // zap the value to avoid the unnecessary assignment
+        // Construct the call to Runtime_InitializeVarGlobal
+        // and add it to the initialization statement block.
+        initialize =
+            factory()->NewCallRuntime(Runtime::kInitializeVarGlobal, arguments,
+                                      descriptor_->declaration_pos);
+      } else {
+        initialize = NULL;
+      }
+    }
+
+    if (initialize != NULL) {
+      block_->statements()->Add(
+          factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
+          zone());
+    }
+  } else if (value != nullptr && (descriptor_->mode == CONST_LEGACY ||
+                                  IsLexicalVariableMode(descriptor_->mode))) {
+    // Constant initializations always assign to the declared constant which
+    // is always at the function scope level. This is only relevant for
+    // dynamically looked-up variables and constants (the
+    // start context for constant lookups is always the function context,
+    // while it is the top context for var declared variables). Sigh...
+    // For 'let' and 'const' declared variables in harmony mode the
+    // initialization also always assigns to the declared variable.
+    DCHECK_NOT_NULL(proxy);
+    DCHECK_NOT_NULL(proxy->var());
+    DCHECK_NOT_NULL(value);
+    // Add break location for destructured sub-pattern.
+    int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
+    Assignment* assignment =
+        factory()->NewAssignment(Token::INIT, proxy, value, pos);
+    block_->statements()->Add(
+        factory()->NewExpressionStatement(assignment, pos), zone());
+    value = NULL;
+  }
+
+  // Add an assignment node to the initialization statement block if we still
+  // have a pending initialization value.
+  if (value != NULL) {
+    DCHECK(descriptor_->mode == VAR);
+    // 'var' initializations are simply assignments (with all the consequences
+    // if they are inside a 'with' statement - they may change a 'with' object
+    // property).
+    VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name);
+    // Add break location for destructured sub-pattern.
+    int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
+    Assignment* assignment =
+        factory()->NewAssignment(Token::INIT, proxy, value, pos);
+    block_->statements()->Add(
+        factory()->NewExpressionStatement(assignment, pos), zone());
+  }
+}
+
+
+Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
+  auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
+  if (value != nullptr) {
+    auto assignment = factory()->NewAssignment(
+        Token::ASSIGN, factory()->NewVariableProxy(temp), value,
+        RelocInfo::kNoPosition);
+
+    block_->statements()->Add(
+        factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
+        zone());
+  }
+  return temp;
+}
+
+
+void Parser::PatternRewriter::VisitRewritableAssignmentExpression(
+    RewritableAssignmentExpression* node) {
+  if (!IsAssignmentContext()) {
+    // Mark the assignment as rewritten to prevent redundant rewriting, and
+    // perform BindingPattern rewriting
+    DCHECK(!node->is_rewritten());
+    node->Rewrite(node->expression());
+    return node->expression()->Accept(this);
+  }
+
+  if (node->is_rewritten()) return;
+  DCHECK(IsAssignmentContext());
+  Assignment* assign = node->expression()->AsAssignment();
+  DCHECK_NOT_NULL(assign);
+  DCHECK_EQ(Token::ASSIGN, assign->op());
+
+  auto initializer = assign->value();
+  auto value = initializer;
+
+  if (IsInitializerContext()) {
+    // let {<pattern> = <init>} = <value>
+    //   becomes
+    // temp = <value>;
+    // <pattern> = temp === undefined ? <init> : temp;
+    auto temp_var = CreateTempVar(current_value_);
+    Expression* is_undefined = factory()->NewCompareOperation(
+        Token::EQ_STRICT, factory()->NewVariableProxy(temp_var),
+        factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+        RelocInfo::kNoPosition);
+    value = factory()->NewConditional(is_undefined, initializer,
+                                      factory()->NewVariableProxy(temp_var),
+                                      RelocInfo::kNoPosition);
+  }
+
+  PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
+  int pos = assign->position();
+  Block* old_block = block_;
+  block_ = factory()->NewBlock(nullptr, 8, false, pos);
+  Variable* temp = nullptr;
+  Expression* pattern = assign->target();
+  Expression* old_value = current_value_;
+  current_value_ = value;
+  if (pattern->IsObjectLiteral()) {
+    VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
+  } else {
+    DCHECK(pattern->IsArrayLiteral());
+    VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
+  }
+  DCHECK_NOT_NULL(temp);
+  current_value_ = old_value;
+  Expression* expr = factory()->NewDoExpression(block_, temp, pos);
+  node->Rewrite(expr);
+  block_ = old_block;
+  if (block_) {
+    block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
+                              zone());
+  }
+  return set_context(old_context);
+}
+
+
+void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
+                                                 Variable** temp_var) {
+  auto temp = *temp_var = CreateTempVar(current_value_);
+
+  block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
+
+  for (ObjectLiteralProperty* property : *pattern->properties()) {
+    PatternContext context = SetInitializerContextIfNeeded(property->value());
+    RecurseIntoSubpattern(
+        property->value(),
+        factory()->NewProperty(factory()->NewVariableProxy(temp),
+                               property->key(), RelocInfo::kNoPosition));
+    set_context(context);
+  }
+}
+
+
+void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
+  Variable* temp_var = nullptr;
+  VisitObjectLiteral(node, &temp_var);
+}
+
+
+void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
+                                                Variable** temp_var) {
+  auto temp = *temp_var = CreateTempVar(current_value_);
+
+  block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
+
+  auto iterator = CreateTempVar(parser_->GetIterator(
+      factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
+  auto done = CreateTempVar(
+      factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
+  auto result = CreateTempVar();
+  auto v = CreateTempVar();
+
+  Spread* spread = nullptr;
+  for (Expression* value : *node->values()) {
+    if (value->IsSpread()) {
+      spread = value->AsSpread();
+      break;
+    }
+
+    PatternContext context = SetInitializerContextIfNeeded(value);
+    // if (!done) {
+    //   result = IteratorNext(iterator);
+    //   v = (done = result.done) ? undefined : result.value;
+    // }
+    auto next_block =
+        factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
+    next_block->statements()->Add(factory()->NewExpressionStatement(
+                                      parser_->BuildIteratorNextResult(
+                                          factory()->NewVariableProxy(iterator),
+                                          result, RelocInfo::kNoPosition),
+                                      RelocInfo::kNoPosition),
+                                  zone());
+
+    auto assign_to_done = factory()->NewAssignment(
+        Token::ASSIGN, factory()->NewVariableProxy(done),
+        factory()->NewProperty(
+            factory()->NewVariableProxy(result),
+            factory()->NewStringLiteral(ast_value_factory()->done_string(),
+                                        RelocInfo::kNoPosition),
+            RelocInfo::kNoPosition),
+        RelocInfo::kNoPosition);
+    auto next_value = factory()->NewConditional(
+        assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+        factory()->NewProperty(
+            factory()->NewVariableProxy(result),
+            factory()->NewStringLiteral(ast_value_factory()->value_string(),
+                                        RelocInfo::kNoPosition),
+            RelocInfo::kNoPosition),
+        RelocInfo::kNoPosition);
+    next_block->statements()->Add(
+        factory()->NewExpressionStatement(
+            factory()->NewAssignment(Token::ASSIGN,
+                                     factory()->NewVariableProxy(v), next_value,
+                                     RelocInfo::kNoPosition),
+            RelocInfo::kNoPosition),
+        zone());
+
+    auto if_statement = factory()->NewIfStatement(
+        factory()->NewUnaryOperation(Token::NOT,
+                                     factory()->NewVariableProxy(done),
+                                     RelocInfo::kNoPosition),
+        next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
+        RelocInfo::kNoPosition);
+    block_->statements()->Add(if_statement, zone());
+
+    if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
+      RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
+    }
+    set_context(context);
+  }
+
+  if (spread != nullptr) {
+    // array = [];
+    // if (!done) %concat_iterable_to_array(array, iterator);
+    auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
+    auto array = CreateTempVar(factory()->NewArrayLiteral(
+        empty_exprs,
+        // Reuse pattern's literal index - it is unused since there is no
+        // actual literal allocated.
+        node->literal_index(), is_strong(scope()->language_mode()),
+        RelocInfo::kNoPosition));
+
+    auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
+    arguments->Add(factory()->NewVariableProxy(array), zone());
+    arguments->Add(factory()->NewVariableProxy(iterator), zone());
+    auto spread_into_array_call =
+        factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
+                                  arguments, RelocInfo::kNoPosition);
+
+    auto if_statement = factory()->NewIfStatement(
+        factory()->NewUnaryOperation(Token::NOT,
+                                     factory()->NewVariableProxy(done),
+                                     RelocInfo::kNoPosition),
+        factory()->NewExpressionStatement(spread_into_array_call,
+                                          RelocInfo::kNoPosition),
+        factory()->NewEmptyStatement(RelocInfo::kNoPosition),
+        RelocInfo::kNoPosition);
+    block_->statements()->Add(if_statement, zone());
+
+    RecurseIntoSubpattern(spread->expression(),
+                          factory()->NewVariableProxy(array));
+  }
+}
+
+
+void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
+  Variable* temp_var = nullptr;
+  VisitArrayLiteral(node, &temp_var);
+}
+
+
+void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
+  // let {<pattern> = <init>} = <value>
+  //   becomes
+  // temp = <value>;
+  // <pattern> = temp === undefined ? <init> : temp;
+  DCHECK_EQ(Token::ASSIGN, node->op());
+
+  auto initializer = node->value();
+  auto value = initializer;
+  auto temp = CreateTempVar(current_value_);
+
+  if (IsInitializerContext()) {
+    Expression* is_undefined = factory()->NewCompareOperation(
+        Token::EQ_STRICT, factory()->NewVariableProxy(temp),
+        factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+        RelocInfo::kNoPosition);
+    value = factory()->NewConditional(is_undefined, initializer,
+                                      factory()->NewVariableProxy(temp),
+                                      RelocInfo::kNoPosition);
+  }
+
+  if (IsBindingContext() &&
+      descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
+      scope()->is_arrow_scope()) {
+    RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
+                                     scope()->outer_scope(), scope());
+  }
+
+  PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
+  RecurseIntoSubpattern(node->target(), value);
+  set_context(old_context);
+}
+
+
+// =============== AssignmentPattern only ==================
+
+void Parser::PatternRewriter::VisitProperty(v8::internal::Property* node) {
+  DCHECK(IsAssignmentContext());
+  auto value = current_value_;
+
+  Assignment* assignment =
+      factory()->NewAssignment(Token::ASSIGN, node, value, node->position());
+
+  block_->statements()->Add(
+      factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
+      zone());
+}
+
+
+// =============== UNREACHABLE =============================
+
+void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); }
+
+#define NOT_A_PATTERN(Node)                                        \
+  void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \
+    UNREACHABLE();                                                 \
+  }
+
+NOT_A_PATTERN(BinaryOperation)
+NOT_A_PATTERN(Block)
+NOT_A_PATTERN(BreakStatement)
+NOT_A_PATTERN(Call)
+NOT_A_PATTERN(CallNew)
+NOT_A_PATTERN(CallRuntime)
+NOT_A_PATTERN(CaseClause)
+NOT_A_PATTERN(ClassLiteral)
+NOT_A_PATTERN(CompareOperation)
+NOT_A_PATTERN(Conditional)
+NOT_A_PATTERN(ContinueStatement)
+NOT_A_PATTERN(CountOperation)
+NOT_A_PATTERN(DebuggerStatement)
+NOT_A_PATTERN(DoExpression)
+NOT_A_PATTERN(DoWhileStatement)
+NOT_A_PATTERN(EmptyStatement)
+NOT_A_PATTERN(EmptyParentheses)
+NOT_A_PATTERN(ExportDeclaration)
+NOT_A_PATTERN(ExpressionStatement)
+NOT_A_PATTERN(ForInStatement)
+NOT_A_PATTERN(ForOfStatement)
+NOT_A_PATTERN(ForStatement)
+NOT_A_PATTERN(FunctionDeclaration)
+NOT_A_PATTERN(FunctionLiteral)
+NOT_A_PATTERN(IfStatement)
+NOT_A_PATTERN(ImportDeclaration)
+NOT_A_PATTERN(Literal)
+NOT_A_PATTERN(NativeFunctionLiteral)
+NOT_A_PATTERN(RegExpLiteral)
+NOT_A_PATTERN(ReturnStatement)
+NOT_A_PATTERN(SloppyBlockFunctionStatement)
+NOT_A_PATTERN(Spread)
+NOT_A_PATTERN(SuperPropertyReference)
+NOT_A_PATTERN(SuperCallReference)
+NOT_A_PATTERN(SwitchStatement)
+NOT_A_PATTERN(ThisFunction)
+NOT_A_PATTERN(Throw)
+NOT_A_PATTERN(TryCatchStatement)
+NOT_A_PATTERN(TryFinallyStatement)
+NOT_A_PATTERN(UnaryOperation)
+NOT_A_PATTERN(VariableDeclaration)
+NOT_A_PATTERN(WhileStatement)
+NOT_A_PATTERN(WithStatement)
+NOT_A_PATTERN(Yield)
+
+#undef NOT_A_PATTERN
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/preparse-data-format.h b/src/parsing/preparse-data-format.h
new file mode 100644
index 0000000..f7d9f68
--- /dev/null
+++ b/src/parsing/preparse-data-format.h
@@ -0,0 +1,41 @@
+// Copyright 2011 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_PREPARSE_DATA_FORMAT_H_
+#define V8_PARSING_PREPARSE_DATA_FORMAT_H_
+
+namespace v8 {
+namespace internal {
+
+// Generic and general data used by preparse data recorders and readers.
+
+struct PreparseDataConstants {
+ public:
+  // Layout and constants of the preparse data exchange format.
+  static const unsigned kMagicNumber = 0xBadDead;
+  static const unsigned kCurrentVersion = 11;
+
+  static const int kMagicOffset = 0;
+  static const int kVersionOffset = 1;
+  static const int kHasErrorOffset = 2;
+  static const int kFunctionsSizeOffset = 3;
+  static const int kSizeOffset = 4;
+  static const int kHeaderSize = 5;
+
+  // If encoding a message, the following positions are fixed.
+  static const int kMessageStartPos = 0;
+  static const int kMessageEndPos = 1;
+  static const int kMessageArgCountPos = 2;
+  static const int kParseErrorTypePos = 3;
+  static const int kMessageTemplatePos = 4;
+  static const int kMessageArgPos = 5;
+
+  static const unsigned char kNumberTerminator = 0x80u;
+};
+
+
+}  // namespace internal
+}  // namespace v8.
+
+#endif  // V8_PARSING_PREPARSE_DATA_FORMAT_H_
diff --git a/src/parsing/preparse-data.cc b/src/parsing/preparse-data.cc
new file mode 100644
index 0000000..d02cd63
--- /dev/null
+++ b/src/parsing/preparse-data.cc
@@ -0,0 +1,80 @@
+// Copyright 2010 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.
+
+#include "src/base/logging.h"
+#include "src/globals.h"
+#include "src/hashmap.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/preparse-data.h"
+#include "src/parsing/preparse-data-format.h"
+
+namespace v8 {
+namespace internal {
+
+
+CompleteParserRecorder::CompleteParserRecorder() {
+  preamble_[PreparseDataConstants::kMagicOffset] =
+      PreparseDataConstants::kMagicNumber;
+  preamble_[PreparseDataConstants::kVersionOffset] =
+      PreparseDataConstants::kCurrentVersion;
+  preamble_[PreparseDataConstants::kHasErrorOffset] = false;
+  preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0;
+  preamble_[PreparseDataConstants::kSizeOffset] = 0;
+  DCHECK_EQ(5, PreparseDataConstants::kHeaderSize);
+#ifdef DEBUG
+  prev_start_ = -1;
+#endif
+}
+
+
+void CompleteParserRecorder::LogMessage(int start_pos, int end_pos,
+                                        MessageTemplate::Template message,
+                                        const char* arg_opt,
+                                        ParseErrorType error_type) {
+  if (HasError()) return;
+  preamble_[PreparseDataConstants::kHasErrorOffset] = true;
+  function_store_.Reset();
+  STATIC_ASSERT(PreparseDataConstants::kMessageStartPos == 0);
+  function_store_.Add(start_pos);
+  STATIC_ASSERT(PreparseDataConstants::kMessageEndPos == 1);
+  function_store_.Add(end_pos);
+  STATIC_ASSERT(PreparseDataConstants::kMessageArgCountPos == 2);
+  function_store_.Add((arg_opt == NULL) ? 0 : 1);
+  STATIC_ASSERT(PreparseDataConstants::kParseErrorTypePos == 3);
+  function_store_.Add(error_type);
+  STATIC_ASSERT(PreparseDataConstants::kMessageTemplatePos == 4);
+  function_store_.Add(static_cast<unsigned>(message));
+  STATIC_ASSERT(PreparseDataConstants::kMessageArgPos == 5);
+  if (arg_opt != NULL) WriteString(CStrVector(arg_opt));
+}
+
+
+void CompleteParserRecorder::WriteString(Vector<const char> str) {
+  function_store_.Add(str.length());
+  for (int i = 0; i < str.length(); i++) {
+    function_store_.Add(str[i]);
+  }
+}
+
+
+ScriptData* CompleteParserRecorder::GetScriptData() {
+  int function_size = function_store_.size();
+  int total_size = PreparseDataConstants::kHeaderSize + function_size;
+  unsigned* data = NewArray<unsigned>(total_size);
+  preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
+  MemCopy(data, preamble_, sizeof(preamble_));
+  if (function_size > 0) {
+    function_store_.WriteTo(Vector<unsigned>(
+        data + PreparseDataConstants::kHeaderSize, function_size));
+  }
+  DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment));
+  ScriptData* result = new ScriptData(reinterpret_cast<byte*>(data),
+                                      total_size * sizeof(unsigned));
+  result->AcquireDataOwnership();
+  return result;
+}
+
+
+}  // namespace internal
+}  // namespace v8.
diff --git a/src/parsing/preparse-data.h b/src/parsing/preparse-data.h
new file mode 100644
index 0000000..dbe1022
--- /dev/null
+++ b/src/parsing/preparse-data.h
@@ -0,0 +1,212 @@
+// Copyright 2011 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_PREPARSE_DATA_H_
+#define V8_PARSING_PREPARSE_DATA_H_
+
+#include "src/allocation.h"
+#include "src/hashmap.h"
+#include "src/messages.h"
+#include "src/parsing/preparse-data-format.h"
+
+namespace v8 {
+namespace internal {
+
+class ScriptData {
+ public:
+  ScriptData(const byte* data, int length);
+  ~ScriptData() {
+    if (owns_data_) DeleteArray(data_);
+  }
+
+  const byte* data() const { return data_; }
+  int length() const { return length_; }
+  bool rejected() const { return rejected_; }
+
+  void Reject() { rejected_ = true; }
+
+  void AcquireDataOwnership() {
+    DCHECK(!owns_data_);
+    owns_data_ = true;
+  }
+
+  void ReleaseDataOwnership() {
+    DCHECK(owns_data_);
+    owns_data_ = false;
+  }
+
+ private:
+  bool owns_data_ : 1;
+  bool rejected_ : 1;
+  const byte* data_;
+  int length_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScriptData);
+};
+
+// Abstract interface for preparse data recorder.
+class ParserRecorder {
+ public:
+  ParserRecorder() { }
+  virtual ~ParserRecorder() { }
+
+  // Logs the scope and some details of a function literal in the source.
+  virtual void LogFunction(int start, int end, int literals, int properties,
+                           LanguageMode language_mode, bool uses_super_property,
+                           bool calls_eval) = 0;
+
+  // Logs an error message and marks the log as containing an error.
+  // Further logging will be ignored, and ExtractData will return a vector
+  // representing the error only.
+  virtual void LogMessage(int start, int end, MessageTemplate::Template message,
+                          const char* argument_opt,
+                          ParseErrorType error_type) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ParserRecorder);
+};
+
+
+class SingletonLogger : public ParserRecorder {
+ public:
+  SingletonLogger()
+      : has_error_(false), start_(-1), end_(-1), error_type_(kSyntaxError) {}
+  virtual ~SingletonLogger() {}
+
+  void Reset() { has_error_ = false; }
+
+  virtual void LogFunction(int start, int end, int literals, int properties,
+                           LanguageMode language_mode, bool uses_super_property,
+                           bool calls_eval) {
+    DCHECK(!has_error_);
+    start_ = start;
+    end_ = end;
+    literals_ = literals;
+    properties_ = properties;
+    language_mode_ = language_mode;
+    uses_super_property_ = uses_super_property;
+    calls_eval_ = calls_eval;
+  }
+
+  // Logs an error message and marks the log as containing an error.
+  // Further logging will be ignored, and ExtractData will return a vector
+  // representing the error only.
+  virtual void LogMessage(int start, int end, MessageTemplate::Template message,
+                          const char* argument_opt, ParseErrorType error_type) {
+    if (has_error_) return;
+    has_error_ = true;
+    start_ = start;
+    end_ = end;
+    message_ = message;
+    argument_opt_ = argument_opt;
+    error_type_ = error_type;
+  }
+
+  bool has_error() const { return has_error_; }
+
+  int start() const { return start_; }
+  int end() const { return end_; }
+  int literals() const {
+    DCHECK(!has_error_);
+    return literals_;
+  }
+  int properties() const {
+    DCHECK(!has_error_);
+    return properties_;
+  }
+  LanguageMode language_mode() const {
+    DCHECK(!has_error_);
+    return language_mode_;
+  }
+  bool uses_super_property() const {
+    DCHECK(!has_error_);
+    return uses_super_property_;
+  }
+  bool calls_eval() const {
+    DCHECK(!has_error_);
+    return calls_eval_;
+  }
+  ParseErrorType error_type() const {
+    DCHECK(has_error_);
+    return error_type_;
+  }
+  MessageTemplate::Template message() {
+    DCHECK(has_error_);
+    return message_;
+  }
+  const char* argument_opt() const {
+    DCHECK(has_error_);
+    return argument_opt_;
+  }
+
+ private:
+  bool has_error_;
+  int start_;
+  int end_;
+  // For function entries.
+  int literals_;
+  int properties_;
+  LanguageMode language_mode_;
+  bool uses_super_property_;
+  bool calls_eval_;
+  // For error messages.
+  MessageTemplate::Template message_;
+  const char* argument_opt_;
+  ParseErrorType error_type_;
+};
+
+
+class CompleteParserRecorder : public ParserRecorder {
+ public:
+  struct Key {
+    bool is_one_byte;
+    Vector<const byte> literal_bytes;
+  };
+
+  CompleteParserRecorder();
+  virtual ~CompleteParserRecorder() {}
+
+  virtual void LogFunction(int start, int end, int literals, int properties,
+                           LanguageMode language_mode, bool uses_super_property,
+                           bool calls_eval) {
+    function_store_.Add(start);
+    function_store_.Add(end);
+    function_store_.Add(literals);
+    function_store_.Add(properties);
+    function_store_.Add(language_mode);
+    function_store_.Add(uses_super_property);
+    function_store_.Add(calls_eval);
+  }
+
+  // Logs an error message and marks the log as containing an error.
+  // Further logging will be ignored, and ExtractData will return a vector
+  // representing the error only.
+  virtual void LogMessage(int start, int end, MessageTemplate::Template message,
+                          const char* argument_opt, ParseErrorType error_type);
+  ScriptData* GetScriptData();
+
+  bool HasError() {
+    return static_cast<bool>(preamble_[PreparseDataConstants::kHasErrorOffset]);
+  }
+  Vector<unsigned> ErrorMessageData() {
+    DCHECK(HasError());
+    return function_store_.ToVector();
+  }
+
+ private:
+  void WriteString(Vector<const char> str);
+
+  Collector<unsigned> function_store_;
+  unsigned preamble_[PreparseDataConstants::kHeaderSize];
+
+#ifdef DEBUG
+  int prev_start_;
+#endif
+};
+
+
+}  // namespace internal
+}  // namespace v8.
+
+#endif  // V8_PARSING_PREPARSE_DATA_H_
diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc
new file mode 100644
index 0000000..64511ac
--- /dev/null
+++ b/src/parsing/preparser.cc
@@ -0,0 +1,1292 @@
+// Copyright 2011 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.
+
+#include <cmath>
+
+#include "src/allocation.h"
+#include "src/base/logging.h"
+#include "src/conversions-inl.h"
+#include "src/conversions.h"
+#include "src/globals.h"
+#include "src/hashmap.h"
+#include "src/list.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/unicode.h"
+#include "src/utils.h"
+
+namespace v8 {
+namespace internal {
+
+void PreParserTraits::ReportMessageAt(Scanner::Location location,
+                                      MessageTemplate::Template message,
+                                      const char* arg,
+                                      ParseErrorType error_type) {
+  ReportMessageAt(location.beg_pos, location.end_pos, message, arg, error_type);
+}
+
+
+void PreParserTraits::ReportMessageAt(int start_pos, int end_pos,
+                                      MessageTemplate::Template message,
+                                      const char* arg,
+                                      ParseErrorType error_type) {
+  pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg, error_type);
+}
+
+
+PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
+  if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
+    return PreParserIdentifier::FutureReserved();
+  } else if (scanner->current_token() ==
+             Token::FUTURE_STRICT_RESERVED_WORD) {
+    return PreParserIdentifier::FutureStrictReserved();
+  } else if (scanner->current_token() == Token::LET) {
+    return PreParserIdentifier::Let();
+  } else if (scanner->current_token() == Token::STATIC) {
+    return PreParserIdentifier::Static();
+  } else if (scanner->current_token() == Token::YIELD) {
+    return PreParserIdentifier::Yield();
+  }
+  if (scanner->UnescapedLiteralMatches("eval", 4)) {
+    return PreParserIdentifier::Eval();
+  }
+  if (scanner->UnescapedLiteralMatches("arguments", 9)) {
+    return PreParserIdentifier::Arguments();
+  }
+  if (scanner->UnescapedLiteralMatches("undefined", 9)) {
+    return PreParserIdentifier::Undefined();
+  }
+  if (scanner->LiteralMatches("prototype", 9)) {
+    return PreParserIdentifier::Prototype();
+  }
+  if (scanner->LiteralMatches("constructor", 11)) {
+    return PreParserIdentifier::Constructor();
+  }
+  return PreParserIdentifier::Default();
+}
+
+
+PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) {
+  return PreParserIdentifier::Default();
+}
+
+
+PreParserExpression PreParserTraits::ExpressionFromString(
+    int pos, Scanner* scanner, PreParserFactory* factory) {
+  if (scanner->UnescapedLiteralMatches("use strict", 10)) {
+    return PreParserExpression::UseStrictStringLiteral();
+  } else if (scanner->UnescapedLiteralMatches("use strong", 10)) {
+    return PreParserExpression::UseStrongStringLiteral();
+  }
+  return PreParserExpression::StringLiteral();
+}
+
+
+PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
+  return pre_parser_->ParseV8Intrinsic(ok);
+}
+
+
+PreParserExpression PreParserTraits::ParseFunctionLiteral(
+    PreParserIdentifier name, Scanner::Location function_name_location,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
+    int function_token_position, FunctionLiteral::FunctionType type,
+    FunctionLiteral::ArityRestriction arity_restriction,
+    LanguageMode language_mode, bool* ok) {
+  return pre_parser_->ParseFunctionLiteral(
+      name, function_name_location, function_name_validity, kind,
+      function_token_position, type, arity_restriction, language_mode, ok);
+}
+
+
+PreParser::PreParseResult PreParser::PreParseLazyFunction(
+    LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
+    ParserRecorder* log, Scanner::BookmarkScope* bookmark) {
+  log_ = log;
+  // Lazy functions always have trivial outer scopes (no with/catch scopes).
+  Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE);
+  PreParserFactory top_factory(NULL);
+  FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction,
+                          &top_factory);
+  scope_->SetLanguageMode(language_mode);
+  Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
+  if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters();
+  PreParserFactory function_factory(NULL);
+  FunctionState function_state(&function_state_, &scope_, function_scope, kind,
+                               &function_factory);
+  DCHECK_EQ(Token::LBRACE, scanner()->current_token());
+  bool ok = true;
+  int start_position = peek_position();
+  ParseLazyFunctionLiteralBody(&ok, bookmark);
+  if (bookmark && bookmark->HasBeenReset()) {
+    // Do nothing, as we've just aborted scanning this function.
+  } else if (stack_overflow()) {
+    return kPreParseStackOverflow;
+  } else if (!ok) {
+    ReportUnexpectedToken(scanner()->current_token());
+  } else {
+    DCHECK_EQ(Token::RBRACE, scanner()->peek());
+    if (is_strict(scope_->language_mode())) {
+      int end_pos = scanner()->location().end_pos;
+      CheckStrictOctalLiteral(start_position, end_pos, &ok);
+      if (!ok) return kPreParseSuccess;
+
+      if (is_strong(scope_->language_mode()) && IsSubclassConstructor(kind)) {
+        if (!function_state.super_location().IsValid()) {
+          ReportMessageAt(Scanner::Location(start_position, start_position + 1),
+                          MessageTemplate::kStrongSuperCallMissing,
+                          kReferenceError);
+          return kPreParseSuccess;
+        }
+      }
+    }
+  }
+  return kPreParseSuccess;
+}
+
+
+PreParserExpression PreParserTraits::ParseClassLiteral(
+    PreParserIdentifier name, Scanner::Location class_name_location,
+    bool name_is_strict_reserved, int pos, bool* ok) {
+  return pre_parser_->ParseClassLiteral(name, class_name_location,
+                                        name_is_strict_reserved, pos, ok);
+}
+
+
+// Preparsing checks a JavaScript program and emits preparse-data that helps
+// a later parsing to be faster.
+// See preparser-data.h for the data.
+
+// 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.
+
+
+PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
+  // ECMA 262 6th Edition
+  // StatementListItem[Yield, Return] :
+  //   Statement[?Yield, ?Return]
+  //   Declaration[?Yield]
+  //
+  // Declaration[Yield] :
+  //   HoistableDeclaration[?Yield]
+  //   ClassDeclaration[?Yield]
+  //   LexicalDeclaration[In, ?Yield]
+  //
+  // HoistableDeclaration[Yield, Default] :
+  //   FunctionDeclaration[?Yield, ?Default]
+  //   GeneratorDeclaration[?Yield, ?Default]
+  //
+  // LexicalDeclaration[In, Yield] :
+  //   LetOrConst BindingList[?In, ?Yield] ;
+
+  switch (peek()) {
+    case Token::FUNCTION:
+      return ParseFunctionDeclaration(ok);
+    case Token::CLASS:
+      return ParseClassDeclaration(ok);
+    case Token::CONST:
+      if (allow_const()) {
+        return ParseVariableStatement(kStatementListItem, ok);
+      }
+      break;
+    case Token::LET:
+      if (IsNextLetKeyword()) {
+        return ParseVariableStatement(kStatementListItem, ok);
+      }
+      break;
+    default:
+      break;
+  }
+  return ParseStatement(ok);
+}
+
+
+void PreParser::ParseStatementList(int end_token, bool* ok,
+                                   Scanner::BookmarkScope* bookmark) {
+  // SourceElements ::
+  //   (Statement)* <end_token>
+
+  // Bookkeeping for trial parse if bookmark is set:
+  DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
+  bool maybe_reset = bookmark != nullptr;
+  int count_statements = 0;
+
+  bool directive_prologue = true;
+  while (peek() != end_token) {
+    if (directive_prologue && peek() != Token::STRING) {
+      directive_prologue = false;
+    }
+    bool starts_with_identifier = peek() == Token::IDENTIFIER;
+    Scanner::Location token_loc = scanner()->peek_location();
+    Scanner::Location old_this_loc = function_state_->this_location();
+    Scanner::Location old_super_loc = function_state_->super_location();
+    Statement statement = ParseStatementListItem(ok);
+    if (!*ok) return;
+
+    if (is_strong(language_mode()) && scope_->is_function_scope() &&
+        IsClassConstructor(function_state_->kind())) {
+      Scanner::Location this_loc = function_state_->this_location();
+      Scanner::Location super_loc = function_state_->super_location();
+      if (this_loc.beg_pos != old_this_loc.beg_pos &&
+          this_loc.beg_pos != token_loc.beg_pos) {
+        ReportMessageAt(this_loc, MessageTemplate::kStrongConstructorThis);
+        *ok = false;
+        return;
+      }
+      if (super_loc.beg_pos != old_super_loc.beg_pos &&
+          super_loc.beg_pos != token_loc.beg_pos) {
+        ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper);
+        *ok = false;
+        return;
+      }
+    }
+
+    if (directive_prologue) {
+      bool use_strict_found = statement.IsUseStrictLiteral();
+      bool use_strong_found =
+          statement.IsUseStrongLiteral() && allow_strong_mode();
+
+      if (use_strict_found) {
+        scope_->SetLanguageMode(
+            static_cast<LanguageMode>(scope_->language_mode() | STRICT));
+      } else if (use_strong_found) {
+        scope_->SetLanguageMode(static_cast<LanguageMode>(
+            scope_->language_mode() | STRONG));
+        if (IsClassConstructor(function_state_->kind())) {
+          // "use strong" cannot occur in a class constructor body, to avoid
+          // unintuitive strong class object semantics.
+          PreParserTraits::ReportMessageAt(
+              token_loc, MessageTemplate::kStrongConstructorDirective);
+          *ok = false;
+          return;
+        }
+      } else if (!statement.IsStringLiteral()) {
+        directive_prologue = false;
+      }
+
+      if ((use_strict_found || use_strong_found) &&
+          !scope_->HasSimpleParameters()) {
+        // TC39 deemed "use strict" directives to be an error when occurring
+        // in the body of a function with non-simple parameter list, on
+        // 29/7/2015. https://goo.gl/ueA7Ln
+        //
+        // In V8, this also applies to "use strong " directives.
+        PreParserTraits::ReportMessageAt(
+            token_loc, MessageTemplate::kIllegalLanguageModeDirective,
+            use_strict_found ? "use strict" : "use strong");
+        *ok = false;
+        return;
+      }
+    }
+
+    // If we're allowed to reset to a bookmark, we will do so when we see a long
+    // and trivial function.
+    // Our current definition of 'long and trivial' is:
+    // - over 200 statements
+    // - all starting with an identifier (i.e., no if, for, while, etc.)
+    if (maybe_reset && (!starts_with_identifier ||
+                        ++count_statements > kLazyParseTrialLimit)) {
+      if (count_statements > kLazyParseTrialLimit) {
+        bookmark->Reset();
+        return;
+      }
+      maybe_reset = false;
+    }
+  }
+}
+
+
+#define CHECK_OK  ok);                   \
+  if (!*ok) return Statement::Default();  \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+
+PreParser::Statement PreParser::ParseStatement(bool* ok) {
+  // Statement ::
+  //   EmptyStatement
+  //   ...
+
+  if (peek() == Token::SEMICOLON) {
+    Next();
+    return Statement::Default();
+  }
+  return ParseSubStatement(ok);
+}
+
+
+PreParser::Statement PreParser::ParseSubStatement(bool* ok) {
+  // Statement ::
+  //   Block
+  //   VariableStatement
+  //   EmptyStatement
+  //   ExpressionStatement
+  //   IfStatement
+  //   IterationStatement
+  //   ContinueStatement
+  //   BreakStatement
+  //   ReturnStatement
+  //   WithStatement
+  //   LabelledStatement
+  //   SwitchStatement
+  //   ThrowStatement
+  //   TryStatement
+  //   DebuggerStatement
+
+  // Note: Since labels can only be used by 'break' and 'continue'
+  // statements, which themselves are only valid within blocks,
+  // iterations or 'switch' statements (i.e., BreakableStatements),
+  // labels can be simply ignored in all other cases; except for
+  // trivial labeled break statements 'label: break label' which is
+  // parsed into an empty statement.
+
+  // Keep the source position of the statement
+  switch (peek()) {
+    case Token::LBRACE:
+      return ParseBlock(ok);
+
+    case Token::SEMICOLON:
+      if (is_strong(language_mode())) {
+        PreParserTraits::ReportMessageAt(scanner()->peek_location(),
+                                         MessageTemplate::kStrongEmpty);
+        *ok = false;
+        return Statement::Default();
+      }
+      Next();
+      return Statement::Default();
+
+    case Token::IF:
+      return ParseIfStatement(ok);
+
+    case Token::DO:
+      return ParseDoWhileStatement(ok);
+
+    case Token::WHILE:
+      return ParseWhileStatement(ok);
+
+    case Token::FOR:
+      return ParseForStatement(ok);
+
+    case Token::CONTINUE:
+      return ParseContinueStatement(ok);
+
+    case Token::BREAK:
+      return ParseBreakStatement(ok);
+
+    case Token::RETURN:
+      return ParseReturnStatement(ok);
+
+    case Token::WITH:
+      return ParseWithStatement(ok);
+
+    case Token::SWITCH:
+      return ParseSwitchStatement(ok);
+
+    case Token::THROW:
+      return ParseThrowStatement(ok);
+
+    case Token::TRY:
+      return ParseTryStatement(ok);
+
+    case Token::FUNCTION: {
+      Scanner::Location start_location = scanner()->peek_location();
+      Statement statement = ParseFunctionDeclaration(CHECK_OK);
+      Scanner::Location end_location = scanner()->location();
+      if (is_strict(language_mode())) {
+        PreParserTraits::ReportMessageAt(start_location.beg_pos,
+                                         end_location.end_pos,
+                                         MessageTemplate::kStrictFunction);
+        *ok = false;
+        return Statement::Default();
+      } else {
+        return statement;
+      }
+    }
+
+    case Token::DEBUGGER:
+      return ParseDebuggerStatement(ok);
+
+    case Token::VAR:
+      return ParseVariableStatement(kStatement, ok);
+
+    case Token::CONST:
+      // In ES6 CONST is not allowed as a Statement, only as a
+      // LexicalDeclaration, however we continue to allow it in sloppy mode for
+      // backwards compatibility.
+      if (is_sloppy(language_mode()) && allow_legacy_const()) {
+        return ParseVariableStatement(kStatement, ok);
+      }
+
+    // Fall through.
+    default:
+      return ParseExpressionOrLabelledStatement(ok);
+  }
+}
+
+
+PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
+  // FunctionDeclaration ::
+  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
+  // GeneratorDeclaration ::
+  //   'function' '*' Identifier '(' FormalParameterListopt ')'
+  //      '{' FunctionBody '}'
+  Expect(Token::FUNCTION, CHECK_OK);
+  int pos = position();
+  bool is_generator = Check(Token::MUL);
+  bool is_strict_reserved = false;
+  Identifier name = ParseIdentifierOrStrictReservedWord(
+      &is_strict_reserved, CHECK_OK);
+  ParseFunctionLiteral(name, scanner()->location(),
+                       is_strict_reserved ? kFunctionNameIsStrictReserved
+                                          : kFunctionNameValidityUnknown,
+                       is_generator ? FunctionKind::kGeneratorFunction
+                                    : FunctionKind::kNormalFunction,
+                       pos, FunctionLiteral::kDeclaration,
+                       FunctionLiteral::kNormalArity, language_mode(),
+                       CHECK_OK);
+  return Statement::FunctionDeclaration();
+}
+
+
+PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
+  Expect(Token::CLASS, CHECK_OK);
+  if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
+    ReportMessage(MessageTemplate::kSloppyLexical);
+    *ok = false;
+    return Statement::Default();
+  }
+
+  int pos = position();
+  bool is_strict_reserved = false;
+  Identifier name =
+      ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+  ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
+                    CHECK_OK);
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseBlock(bool* ok) {
+  // Block ::
+  //   '{' StatementList '}'
+
+  Expect(Token::LBRACE, CHECK_OK);
+  Statement final = Statement::Default();
+  while (peek() != Token::RBRACE) {
+    final = ParseStatementListItem(CHECK_OK);
+  }
+  Expect(Token::RBRACE, ok);
+  return final;
+}
+
+
+PreParser::Statement PreParser::ParseVariableStatement(
+    VariableDeclarationContext var_context,
+    bool* ok) {
+  // VariableStatement ::
+  //   VariableDeclarations ';'
+
+  Statement result = ParseVariableDeclarations(
+      var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+  return result;
+}
+
+
+// If the variable declaration declares exactly one non-const
+// variable, then *var is set to that variable. In all other cases,
+// *var is untouched; in particular, it is the caller's responsibility
+// to initialize it properly. This mechanism is also used for the parsing
+// of 'for-in' loops.
+PreParser::Statement PreParser::ParseVariableDeclarations(
+    VariableDeclarationContext var_context, int* num_decl, bool* is_lexical,
+    bool* is_binding_pattern, Scanner::Location* first_initializer_loc,
+    Scanner::Location* bindings_loc, bool* ok) {
+  // VariableDeclarations ::
+  //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
+  //
+  // The ES6 Draft Rev3 specifies the following grammar for const declarations
+  //
+  // ConstDeclaration ::
+  //   const ConstBinding (',' ConstBinding)* ';'
+  // ConstBinding ::
+  //   Identifier '=' AssignmentExpression
+  //
+  // TODO(ES6):
+  // ConstBinding ::
+  //   BindingPattern '=' AssignmentExpression
+  bool require_initializer = false;
+  bool lexical = false;
+  bool is_pattern = false;
+  if (peek() == Token::VAR) {
+    if (is_strong(language_mode())) {
+      Scanner::Location location = scanner()->peek_location();
+      ReportMessageAt(location, MessageTemplate::kStrongVar);
+      *ok = false;
+      return Statement::Default();
+    }
+    Consume(Token::VAR);
+  } else if (peek() == Token::CONST && allow_const()) {
+    // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
+    //
+    // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
+    //
+    // * It is a Syntax Error if the code that matches this production is not
+    //   contained in extended code.
+    //
+    // However disallowing const in sloppy mode will break compatibility with
+    // existing pages. Therefore we keep allowing const with the old
+    // non-harmony semantics in sloppy mode.
+    Consume(Token::CONST);
+    if (is_strict(language_mode()) ||
+        (allow_harmony_sloppy() && !allow_legacy_const())) {
+      DCHECK(var_context != kStatement);
+      require_initializer = true;
+      lexical = true;
+    }
+  } else if (peek() == Token::LET && allow_let()) {
+    Consume(Token::LET);
+    DCHECK(var_context != kStatement);
+    lexical = true;
+  } else {
+    *ok = false;
+    return Statement::Default();
+  }
+
+  // The scope of a var/const declared variable anywhere inside a function
+  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
+  // of a let declared variable is the scope of the immediately enclosing
+  // block.
+  int nvars = 0;  // the number of variables declared
+  int bindings_start = peek_position();
+  do {
+    // Parse binding pattern.
+    if (nvars > 0) Consume(Token::COMMA);
+    int decl_pos = peek_position();
+    PreParserExpression pattern = PreParserExpression::Default();
+    {
+      ExpressionClassifier pattern_classifier;
+      Token::Value next = peek();
+      pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
+
+      ValidateBindingPattern(&pattern_classifier, CHECK_OK);
+      if (lexical) {
+        ValidateLetPattern(&pattern_classifier, CHECK_OK);
+      }
+
+      if (!allow_harmony_destructuring_bind() && !pattern.IsIdentifier()) {
+        ReportUnexpectedToken(next);
+        *ok = false;
+        return Statement::Default();
+      }
+    }
+
+    is_pattern = (pattern.IsObjectLiteral() || pattern.IsArrayLiteral()) &&
+                 !pattern.is_parenthesized();
+
+    bool is_for_iteration_variable =
+        var_context == kForStatement &&
+        (peek() == Token::IN || PeekContextualKeyword(CStrVector("of")));
+
+    Scanner::Location variable_loc = scanner()->location();
+    nvars++;
+    if (Check(Token::ASSIGN)) {
+      ExpressionClassifier classifier;
+      ParseAssignmentExpression(var_context != kForStatement, &classifier,
+                                CHECK_OK);
+      ValidateExpression(&classifier, CHECK_OK);
+
+      variable_loc.end_pos = scanner()->location().end_pos;
+      if (first_initializer_loc && !first_initializer_loc->IsValid()) {
+        *first_initializer_loc = variable_loc;
+      }
+    } else if ((require_initializer || is_pattern) &&
+               !is_for_iteration_variable) {
+      PreParserTraits::ReportMessageAt(
+          Scanner::Location(decl_pos, scanner()->location().end_pos),
+          MessageTemplate::kDeclarationMissingInitializer,
+          is_pattern ? "destructuring" : "const");
+      *ok = false;
+      return Statement::Default();
+    }
+  } while (peek() == Token::COMMA);
+
+  if (bindings_loc) {
+    *bindings_loc =
+        Scanner::Location(bindings_start, scanner()->location().end_pos);
+  }
+
+  if (num_decl != nullptr) *num_decl = nvars;
+  if (is_lexical != nullptr) *is_lexical = lexical;
+  if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern;
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
+  // ExpressionStatement | LabelledStatement ::
+  //   Expression ';'
+  //   Identifier ':' Statement
+
+  switch (peek()) {
+    case Token::FUNCTION:
+    case Token::LBRACE:
+      UNREACHABLE();  // Always handled by the callers.
+    case Token::CLASS:
+      ReportUnexpectedToken(Next());
+      *ok = false;
+      return Statement::Default();
+
+    case Token::THIS:
+      if (!FLAG_strong_this) break;
+      // Fall through.
+    case Token::SUPER:
+      if (is_strong(language_mode()) &&
+          IsClassConstructor(function_state_->kind())) {
+        bool is_this = peek() == Token::THIS;
+        Expression expr = Expression::Default();
+        ExpressionClassifier classifier;
+        if (is_this) {
+          expr = ParseStrongInitializationExpression(&classifier, CHECK_OK);
+        } else {
+          expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK);
+        }
+        ValidateExpression(&classifier, CHECK_OK);
+        switch (peek()) {
+          case Token::SEMICOLON:
+            Consume(Token::SEMICOLON);
+            break;
+          case Token::RBRACE:
+          case Token::EOS:
+            break;
+          default:
+            if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
+              ReportMessageAt(function_state_->this_location(),
+                              is_this
+                                  ? MessageTemplate::kStrongConstructorThis
+                                  : MessageTemplate::kStrongConstructorSuper);
+              *ok = false;
+              return Statement::Default();
+            }
+        }
+        return Statement::ExpressionStatement(expr);
+      }
+      break;
+
+    // TODO(arv): Handle `let [`
+    // https://code.google.com/p/v8/issues/detail?id=3847
+
+    default:
+      break;
+  }
+
+  bool starts_with_identifier = peek_any_identifier();
+  ExpressionClassifier classifier;
+  Expression expr = ParseExpression(true, &classifier, CHECK_OK);
+  ValidateExpression(&classifier, CHECK_OK);
+
+  // Even if the expression starts with an identifier, it is not necessarily an
+  // identifier. For example, "foo + bar" starts with an identifier but is not
+  // an identifier.
+  if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
+    // Expression is a single identifier, and not, e.g., a parenthesized
+    // identifier.
+    DCHECK(!expr.AsIdentifier().IsFutureReserved());
+    DCHECK(is_sloppy(language_mode()) ||
+           !IsFutureStrictReserved(expr.AsIdentifier()));
+    Consume(Token::COLON);
+    Statement statement = ParseStatement(ok);
+    return statement.IsJumpStatement() ? Statement::Default() : statement;
+    // 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.
+  }
+  // Parsed expression statement.
+  // Detect attempts at 'let' declarations in sloppy mode.
+  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
+      is_sloppy(language_mode()) && expr.IsIdentifier() &&
+      expr.AsIdentifier().IsLet()) {
+    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
+    *ok = false;
+    return Statement::Default();
+  }
+  ExpectSemicolon(CHECK_OK);
+  return Statement::ExpressionStatement(expr);
+}
+
+
+PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
+  // IfStatement ::
+  //   'if' '(' Expression ')' Statement ('else' Statement)?
+
+  Expect(Token::IF, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+  Statement stat = ParseSubStatement(CHECK_OK);
+  if (peek() == Token::ELSE) {
+    Next();
+    Statement else_stat = ParseSubStatement(CHECK_OK);
+    stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ?
+        Statement::Jump() : Statement::Default();
+  } else {
+    stat = Statement::Default();
+  }
+  return stat;
+}
+
+
+PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
+  // ContinueStatement ::
+  //   'continue' [no line terminator] Identifier? ';'
+
+  Expect(Token::CONTINUE, CHECK_OK);
+  Token::Value tok = peek();
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
+      tok != Token::SEMICOLON &&
+      tok != Token::RBRACE &&
+      tok != Token::EOS) {
+    // ECMA allows "eval" or "arguments" as labels even in strict mode.
+    ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+  }
+  ExpectSemicolon(CHECK_OK);
+  return Statement::Jump();
+}
+
+
+PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
+  // BreakStatement ::
+  //   'break' [no line terminator] Identifier? ';'
+
+  Expect(Token::BREAK, CHECK_OK);
+  Token::Value tok = peek();
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
+      tok != Token::SEMICOLON &&
+      tok != Token::RBRACE &&
+      tok != Token::EOS) {
+    // ECMA allows "eval" or "arguments" as labels even in strict mode.
+    ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+  }
+  ExpectSemicolon(CHECK_OK);
+  return Statement::Jump();
+}
+
+
+PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
+  // ReturnStatement ::
+  //   'return' [no line terminator] Expression? ';'
+
+  // Consume the return token. It is necessary to do before
+  // reporting any errors on it, because of the way errors are
+  // reported (underlining).
+  Expect(Token::RETURN, CHECK_OK);
+  function_state_->set_return_location(scanner()->location());
+
+  // An ECMAScript program is considered syntactically incorrect if it
+  // contains a return statement that is not within the body of a
+  // function. See ECMA-262, section 12.9, page 67.
+  // This is not handled during preparsing.
+
+  Token::Value tok = peek();
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
+      tok != Token::SEMICOLON &&
+      tok != Token::RBRACE &&
+      tok != Token::EOS) {
+    if (is_strong(language_mode()) &&
+        IsClassConstructor(function_state_->kind())) {
+      int pos = peek_position();
+      ReportMessageAt(Scanner::Location(pos, pos + 1),
+                      MessageTemplate::kStrongConstructorReturnValue);
+      *ok = false;
+      return Statement::Default();
+    }
+    ParseExpression(true, CHECK_OK);
+  }
+  ExpectSemicolon(CHECK_OK);
+  return Statement::Jump();
+}
+
+
+PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
+  // WithStatement ::
+  //   'with' '(' Expression ')' Statement
+  Expect(Token::WITH, CHECK_OK);
+  if (is_strict(language_mode())) {
+    ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith);
+    *ok = false;
+    return Statement::Default();
+  }
+  Expect(Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  Scope* with_scope = NewScope(scope_, WITH_SCOPE);
+  BlockState block_state(&scope_, with_scope);
+  ParseSubStatement(CHECK_OK);
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
+  // SwitchStatement ::
+  //   'switch' '(' Expression ')' '{' CaseClause* '}'
+
+  Expect(Token::SWITCH, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  Expect(Token::LBRACE, CHECK_OK);
+  Token::Value token = peek();
+  while (token != Token::RBRACE) {
+    if (token == Token::CASE) {
+      Expect(Token::CASE, CHECK_OK);
+      ParseExpression(true, CHECK_OK);
+    } else {
+      Expect(Token::DEFAULT, CHECK_OK);
+    }
+    Expect(Token::COLON, CHECK_OK);
+    token = peek();
+    Statement statement = Statement::Jump();
+    while (token != Token::CASE &&
+           token != Token::DEFAULT &&
+           token != Token::RBRACE) {
+      statement = ParseStatementListItem(CHECK_OK);
+      token = peek();
+    }
+    if (is_strong(language_mode()) && !statement.IsJumpStatement() &&
+        token != Token::RBRACE) {
+      ReportMessageAt(scanner()->location(),
+                      MessageTemplate::kStrongSwitchFallthrough);
+      *ok = false;
+      return Statement::Default();
+    }
+  }
+  Expect(Token::RBRACE, ok);
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
+  // DoStatement ::
+  //   'do' Statement 'while' '(' Expression ')' ';'
+
+  Expect(Token::DO, CHECK_OK);
+  ParseSubStatement(CHECK_OK);
+  Expect(Token::WHILE, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, ok);
+  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
+  // WhileStatement ::
+  //   'while' '(' Expression ')' Statement
+
+  Expect(Token::WHILE, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+  ParseSubStatement(ok);
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseForStatement(bool* ok) {
+  // ForStatement ::
+  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
+
+  Expect(Token::FOR, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  bool is_let_identifier_expression = false;
+  if (peek() != Token::SEMICOLON) {
+    ForEachStatement::VisitMode mode;
+    if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
+        (peek() == Token::LET && IsNextLetKeyword())) {
+      int decl_count;
+      bool is_lexical;
+      bool is_binding_pattern;
+      Scanner::Location first_initializer_loc = Scanner::Location::invalid();
+      Scanner::Location bindings_loc = Scanner::Location::invalid();
+      ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical,
+                                &is_binding_pattern, &first_initializer_loc,
+                                &bindings_loc, CHECK_OK);
+      bool accept_IN = decl_count >= 1;
+      if (accept_IN && CheckInOrOf(&mode, ok)) {
+        if (!*ok) return Statement::Default();
+        if (decl_count != 1) {
+          const char* loop_type =
+              mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
+          PreParserTraits::ReportMessageAt(
+              bindings_loc, MessageTemplate::kForInOfLoopMultiBindings,
+              loop_type);
+          *ok = false;
+          return Statement::Default();
+        }
+        if (first_initializer_loc.IsValid() &&
+            (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
+             is_lexical || is_binding_pattern)) {
+          if (mode == ForEachStatement::ITERATE) {
+            ReportMessageAt(first_initializer_loc,
+                            MessageTemplate::kForOfLoopInitializer);
+          } else {
+            // TODO(caitp): This should be an error in sloppy mode, too.
+            ReportMessageAt(first_initializer_loc,
+                            MessageTemplate::kForInLoopInitializer);
+          }
+          *ok = false;
+          return Statement::Default();
+        }
+        ParseExpression(true, CHECK_OK);
+        Expect(Token::RPAREN, CHECK_OK);
+        ParseSubStatement(CHECK_OK);
+        return Statement::Default();
+      }
+    } else {
+      int lhs_beg_pos = peek_position();
+      ExpressionClassifier classifier;
+      Expression lhs = ParseExpression(false, &classifier, CHECK_OK);
+      int lhs_end_pos = scanner()->location().end_pos;
+      is_let_identifier_expression =
+          lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
+      bool is_for_each = CheckInOrOf(&mode, ok);
+      if (!*ok) return Statement::Default();
+      bool is_destructuring = is_for_each &&
+                              allow_harmony_destructuring_assignment() &&
+                              (lhs->IsArrayLiteral() || lhs->IsObjectLiteral());
+
+      if (is_destructuring) {
+        ValidateAssignmentPattern(&classifier, CHECK_OK);
+      } else {
+        ValidateExpression(&classifier, CHECK_OK);
+      }
+
+      if (is_for_each) {
+        if (!is_destructuring) {
+          lhs = CheckAndRewriteReferenceExpression(
+              lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
+              kSyntaxError, CHECK_OK);
+        }
+        ParseExpression(true, CHECK_OK);
+        Expect(Token::RPAREN, CHECK_OK);
+        ParseSubStatement(CHECK_OK);
+        return Statement::Default();
+      }
+    }
+  }
+
+  // Parsed initializer at this point.
+  // Detect attempts at 'let' declarations in sloppy mode.
+  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
+      is_sloppy(language_mode()) && is_let_identifier_expression) {
+    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
+    *ok = false;
+    return Statement::Default();
+  }
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  if (peek() != Token::SEMICOLON) {
+    ParseExpression(true, CHECK_OK);
+  }
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  if (peek() != Token::RPAREN) {
+    ParseExpression(true, CHECK_OK);
+  }
+  Expect(Token::RPAREN, CHECK_OK);
+
+  ParseSubStatement(ok);
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
+  // ThrowStatement ::
+  //   'throw' [no line terminator] Expression ';'
+
+  Expect(Token::THROW, CHECK_OK);
+  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
+    ReportMessageAt(scanner()->location(), MessageTemplate::kNewlineAfterThrow);
+    *ok = false;
+    return Statement::Default();
+  }
+  ParseExpression(true, CHECK_OK);
+  ExpectSemicolon(ok);
+  return Statement::Jump();
+}
+
+
+PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
+  // TryStatement ::
+  //   'try' Block Catch
+  //   'try' Block Finally
+  //   'try' Block Catch Finally
+  //
+  // Catch ::
+  //   'catch' '(' Identifier ')' Block
+  //
+  // Finally ::
+  //   'finally' Block
+
+  Expect(Token::TRY, CHECK_OK);
+
+  ParseBlock(CHECK_OK);
+
+  Token::Value tok = peek();
+  if (tok != Token::CATCH && tok != Token::FINALLY) {
+    ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally);
+    *ok = false;
+    return Statement::Default();
+  }
+  if (tok == Token::CATCH) {
+    Consume(Token::CATCH);
+    Expect(Token::LPAREN, CHECK_OK);
+    ExpressionClassifier pattern_classifier;
+    ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
+    ValidateBindingPattern(&pattern_classifier, CHECK_OK);
+    Expect(Token::RPAREN, CHECK_OK);
+    {
+      // TODO(adamk): Make this CATCH_SCOPE
+      Scope* with_scope = NewScope(scope_, WITH_SCOPE);
+      BlockState block_state(&scope_, with_scope);
+      ParseBlock(CHECK_OK);
+    }
+    tok = peek();
+  }
+  if (tok == Token::FINALLY) {
+    Consume(Token::FINALLY);
+    ParseBlock(CHECK_OK);
+  }
+  return Statement::Default();
+}
+
+
+PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
+  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
+  // contexts this is used as a statement which invokes the debugger as if a
+  // break point is present.
+  // DebuggerStatement ::
+  //   'debugger' ';'
+
+  Expect(Token::DEBUGGER, CHECK_OK);
+  ExpectSemicolon(ok);
+  return Statement::Default();
+}
+
+
+#undef CHECK_OK
+#define CHECK_OK  ok);                     \
+  if (!*ok) return Expression::Default();  \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+
+PreParser::Expression PreParser::ParseFunctionLiteral(
+    Identifier function_name, Scanner::Location function_name_location,
+    FunctionNameValidity function_name_validity, FunctionKind kind,
+    int function_token_pos, FunctionLiteral::FunctionType function_type,
+    FunctionLiteral::ArityRestriction arity_restriction,
+    LanguageMode language_mode, bool* ok) {
+  // Function ::
+  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
+
+  // Parse function body.
+  bool outer_is_script_scope = scope_->is_script_scope();
+  Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
+  function_scope->SetLanguageMode(language_mode);
+  PreParserFactory factory(NULL);
+  FunctionState function_state(&function_state_, &scope_, function_scope, kind,
+                               &factory);
+  DuplicateFinder duplicate_finder(scanner()->unicode_cache());
+  ExpressionClassifier formals_classifier(&duplicate_finder);
+
+  Expect(Token::LPAREN, CHECK_OK);
+  int start_position = scanner()->location().beg_pos;
+  function_scope->set_start_position(start_position);
+  PreParserFormalParameters formals(function_scope);
+  ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+  int formals_end_position = scanner()->location().end_pos;
+
+  CheckArityRestrictions(formals.arity, arity_restriction,
+                         formals.has_rest, start_position,
+                         formals_end_position, CHECK_OK);
+
+  // See Parser::ParseFunctionLiteral for more information about lazy parsing
+  // and lazy compilation.
+  bool is_lazily_parsed =
+      (outer_is_script_scope && allow_lazy() && !parenthesized_function_);
+  parenthesized_function_ = false;
+
+  Expect(Token::LBRACE, CHECK_OK);
+  if (is_lazily_parsed) {
+    ParseLazyFunctionLiteralBody(CHECK_OK);
+  } else {
+    ParseStatementList(Token::RBRACE, CHECK_OK);
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+
+  // Parsing the body may change the language mode in our scope.
+  language_mode = function_scope->language_mode();
+
+  // Validate name and parameter names. We can do this only after parsing the
+  // function, since the function can declare itself strict.
+  CheckFunctionName(language_mode, function_name, function_name_validity,
+                    function_name_location, CHECK_OK);
+  const bool allow_duplicate_parameters =
+      is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
+  ValidateFormalParameters(&formals_classifier, language_mode,
+                           allow_duplicate_parameters, CHECK_OK);
+
+  if (is_strict(language_mode)) {
+    int end_position = scanner()->location().end_pos;
+    CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
+  }
+
+  if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
+    if (!function_state.super_location().IsValid()) {
+      ReportMessageAt(function_name_location,
+                      MessageTemplate::kStrongSuperCallMissing,
+                      kReferenceError);
+      *ok = false;
+      return Expression::Default();
+    }
+  }
+
+  return Expression::Default();
+}
+
+
+void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
+                                             Scanner::BookmarkScope* bookmark) {
+  int body_start = position();
+  ParseStatementList(Token::RBRACE, ok, bookmark);
+  if (!*ok) return;
+  if (bookmark && bookmark->HasBeenReset()) return;
+
+  // Position right after terminal '}'.
+  DCHECK_EQ(Token::RBRACE, scanner()->peek());
+  int body_end = scanner()->peek_location().end_pos;
+  log_->LogFunction(body_start, body_end,
+                    function_state_->materialized_literal_count(),
+                    function_state_->expected_property_count(), language_mode(),
+                    scope_->uses_super_property(), scope_->calls_eval());
+}
+
+
+PreParserExpression PreParser::ParseClassLiteral(
+    PreParserIdentifier name, Scanner::Location class_name_location,
+    bool name_is_strict_reserved, int pos, bool* ok) {
+  // All parts of a ClassDeclaration and ClassExpression are strict code.
+  if (name_is_strict_reserved) {
+    ReportMessageAt(class_name_location,
+                    MessageTemplate::kUnexpectedStrictReserved);
+    *ok = false;
+    return EmptyExpression();
+  }
+  if (IsEvalOrArguments(name)) {
+    ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
+    *ok = false;
+    return EmptyExpression();
+  }
+  LanguageMode class_language_mode = language_mode();
+  if (is_strong(class_language_mode) && IsUndefined(name)) {
+    ReportMessageAt(class_name_location, MessageTemplate::kStrongUndefined);
+    *ok = false;
+    return EmptyExpression();
+  }
+
+  Scope* scope = NewScope(scope_, BLOCK_SCOPE);
+  BlockState block_state(&scope_, scope);
+  scope_->SetLanguageMode(
+      static_cast<LanguageMode>(class_language_mode | STRICT));
+  // TODO(marja): Make PreParser use scope names too.
+  // scope_->SetScopeName(name);
+
+  bool has_extends = Check(Token::EXTENDS);
+  if (has_extends) {
+    ExpressionClassifier classifier;
+    ParseLeftHandSideExpression(&classifier, CHECK_OK);
+    ValidateExpression(&classifier, CHECK_OK);
+  }
+
+  ClassLiteralChecker checker(this);
+  bool has_seen_constructor = false;
+
+  Expect(Token::LBRACE, CHECK_OK);
+  while (peek() != Token::RBRACE) {
+    if (Check(Token::SEMICOLON)) continue;
+    const bool in_class = true;
+    const bool is_static = false;
+    bool is_computed_name = false;  // Classes do not care about computed
+                                    // property names here.
+    Identifier name;
+    ExpressionClassifier classifier;
+    ParsePropertyDefinition(&checker, in_class, has_extends, is_static,
+                            &is_computed_name, &has_seen_constructor,
+                            &classifier, &name, CHECK_OK);
+    ValidateExpression(&classifier, CHECK_OK);
+  }
+
+  Expect(Token::RBRACE, CHECK_OK);
+
+  return Expression::Default();
+}
+
+
+PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
+  // CallRuntime ::
+  //   '%' Identifier Arguments
+  Expect(Token::MOD, CHECK_OK);
+  if (!allow_natives()) {
+    *ok = false;
+    return Expression::Default();
+  }
+  // Allow "eval" or "arguments" for backward compatibility.
+  ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+  Scanner::Location spread_pos;
+  ExpressionClassifier classifier;
+  ParseArguments(&spread_pos, &classifier, ok);
+  ValidateExpression(&classifier, CHECK_OK);
+
+  DCHECK(!spread_pos.IsValid());
+
+  return Expression::Default();
+}
+
+
+PreParserExpression PreParser::ParseDoExpression(bool* ok) {
+  // AssignmentExpression ::
+  //     do '{' StatementList '}'
+  Expect(Token::DO, CHECK_OK);
+  Expect(Token::LBRACE, CHECK_OK);
+  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
+  {
+    BlockState block_state(&scope_, block_scope);
+    while (peek() != Token::RBRACE) {
+      ParseStatementListItem(CHECK_OK);
+    }
+    Expect(Token::RBRACE, CHECK_OK);
+    return PreParserExpression::Default();
+  }
+}
+
+#undef CHECK_OK
+
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h
new file mode 100644
index 0000000..59100f1
--- /dev/null
+++ b/src/parsing/preparser.h
@@ -0,0 +1,1175 @@
+// 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/scopes.h"
+#include "src/bailout-reason.h"
+#include "src/hashmap.h"
+#include "src/messages.h"
+#include "src/parsing/expression-classifier.h"
+#include "src/parsing/func-name-inferrer.h"
+#include "src/parsing/parser-base.h"
+#include "src/parsing/scanner.h"
+#include "src/parsing/token.h"
+
+namespace v8 {
+namespace internal {
+
+
+class PreParserIdentifier {
+ public:
+  PreParserIdentifier() : type_(kUnknownIdentifier) {}
+  static PreParserIdentifier Default() {
+    return PreParserIdentifier(kUnknownIdentifier);
+  }
+  static PreParserIdentifier Eval() {
+    return PreParserIdentifier(kEvalIdentifier);
+  }
+  static PreParserIdentifier Arguments() {
+    return PreParserIdentifier(kArgumentsIdentifier);
+  }
+  static PreParserIdentifier Undefined() {
+    return PreParserIdentifier(kUndefinedIdentifier);
+  }
+  static PreParserIdentifier FutureReserved() {
+    return PreParserIdentifier(kFutureReservedIdentifier);
+  }
+  static PreParserIdentifier FutureStrictReserved() {
+    return PreParserIdentifier(kFutureStrictReservedIdentifier);
+  }
+  static PreParserIdentifier Let() {
+    return PreParserIdentifier(kLetIdentifier);
+  }
+  static PreParserIdentifier Static() {
+    return PreParserIdentifier(kStaticIdentifier);
+  }
+  static PreParserIdentifier Yield() {
+    return PreParserIdentifier(kYieldIdentifier);
+  }
+  static PreParserIdentifier Prototype() {
+    return PreParserIdentifier(kPrototypeIdentifier);
+  }
+  static PreParserIdentifier Constructor() {
+    return PreParserIdentifier(kConstructorIdentifier);
+  }
+  bool IsEval() const { return type_ == kEvalIdentifier; }
+  bool IsArguments() const { return type_ == kArgumentsIdentifier; }
+  bool IsEvalOrArguments() const { return IsEval() || IsArguments(); }
+  bool IsUndefined() const { return type_ == kUndefinedIdentifier; }
+  bool IsLet() const { return type_ == kLetIdentifier; }
+  bool IsStatic() const { return type_ == kStaticIdentifier; }
+  bool IsYield() const { return type_ == kYieldIdentifier; }
+  bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
+  bool IsConstructor() const { return type_ == kConstructorIdentifier; }
+  bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; }
+  bool IsFutureStrictReserved() const {
+    return type_ == kFutureStrictReservedIdentifier ||
+           type_ == kLetIdentifier || type_ == kStaticIdentifier ||
+           type_ == kYieldIdentifier;
+  }
+
+  // Allow identifier->name()[->length()] to work. The preparser
+  // does not need the actual positions/lengths of the identifiers.
+  const PreParserIdentifier* operator->() const { return this; }
+  const PreParserIdentifier raw_name() const { return *this; }
+
+  int position() const { return 0; }
+  int length() const { return 0; }
+
+ private:
+  enum Type {
+    kUnknownIdentifier,
+    kFutureReservedIdentifier,
+    kFutureStrictReservedIdentifier,
+    kLetIdentifier,
+    kStaticIdentifier,
+    kYieldIdentifier,
+    kEvalIdentifier,
+    kArgumentsIdentifier,
+    kUndefinedIdentifier,
+    kPrototypeIdentifier,
+    kConstructorIdentifier
+  };
+
+  explicit PreParserIdentifier(Type type) : type_(type) {}
+  Type type_;
+
+  friend class PreParserExpression;
+};
+
+
+class PreParserExpression {
+ public:
+  static PreParserExpression Default() {
+    return PreParserExpression(TypeField::encode(kExpression));
+  }
+
+  static PreParserExpression Spread(PreParserExpression expression) {
+    return PreParserExpression(TypeField::encode(kSpreadExpression));
+  }
+
+  static PreParserExpression FromIdentifier(PreParserIdentifier id) {
+    return PreParserExpression(TypeField::encode(kIdentifierExpression) |
+                               IdentifierTypeField::encode(id.type_));
+  }
+
+  static PreParserExpression BinaryOperation(PreParserExpression left,
+                                             Token::Value op,
+                                             PreParserExpression right) {
+    return PreParserExpression(TypeField::encode(kBinaryOperationExpression));
+  }
+
+  static PreParserExpression Assignment() {
+    return PreParserExpression(TypeField::encode(kExpression) |
+                               ExpressionTypeField::encode(kAssignment));
+  }
+
+  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 UseStrictStringLiteral() {
+    return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
+                               IsUseStrictField::encode(true));
+  }
+
+  static PreParserExpression UseStrongStringLiteral() {
+    return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
+                               IsUseStrongField::encode(true));
+  }
+
+  static PreParserExpression This() {
+    return PreParserExpression(TypeField::encode(kExpression) |
+                               ExpressionTypeField::encode(kThisExpression));
+  }
+
+  static PreParserExpression ThisProperty() {
+    return PreParserExpression(
+        TypeField::encode(kExpression) |
+        ExpressionTypeField::encode(kThisPropertyExpression));
+  }
+
+  static PreParserExpression Property() {
+    return PreParserExpression(
+        TypeField::encode(kExpression) |
+        ExpressionTypeField::encode(kPropertyExpression));
+  }
+
+  static PreParserExpression Call() {
+    return PreParserExpression(TypeField::encode(kExpression) |
+                               ExpressionTypeField::encode(kCallExpression));
+  }
+
+  static PreParserExpression SuperCallReference() {
+    return PreParserExpression(
+        TypeField::encode(kExpression) |
+        ExpressionTypeField::encode(kSuperCallReference));
+  }
+
+  static PreParserExpression NoTemplateTag() {
+    return PreParserExpression(
+        TypeField::encode(kExpression) |
+        ExpressionTypeField::encode(kNoTemplateTagExpression));
+  }
+
+  bool IsIdentifier() const {
+    return TypeField::decode(code_) == kIdentifierExpression;
+  }
+
+  PreParserIdentifier AsIdentifier() const {
+    DCHECK(IsIdentifier());
+    return PreParserIdentifier(IdentifierTypeField::decode(code_));
+  }
+
+  bool IsAssignment() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kAssignment;
+  }
+
+  bool IsObjectLiteral() const {
+    return TypeField::decode(code_) == kObjectLiteralExpression;
+  }
+
+  bool IsArrayLiteral() const {
+    return TypeField::decode(code_) == kArrayLiteralExpression;
+  }
+
+  bool IsStringLiteral() const {
+    return TypeField::decode(code_) == kStringLiteralExpression;
+  }
+
+  bool IsUseStrictLiteral() const {
+    return TypeField::decode(code_) == kStringLiteralExpression &&
+           IsUseStrictField::decode(code_);
+  }
+
+  bool IsUseStrongLiteral() const {
+    return TypeField::decode(code_) == kStringLiteralExpression &&
+           IsUseStrongField::decode(code_);
+  }
+
+  bool IsThis() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kThisExpression;
+  }
+
+  bool IsThisProperty() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kThisPropertyExpression;
+  }
+
+  bool IsProperty() const {
+    return TypeField::decode(code_) == kExpression &&
+           (ExpressionTypeField::decode(code_) == kPropertyExpression ||
+            ExpressionTypeField::decode(code_) == kThisPropertyExpression);
+  }
+
+  bool IsCall() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kCallExpression;
+  }
+
+  bool IsSuperCallReference() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kSuperCallReference;
+  }
+
+  bool IsValidReferenceExpression() const {
+    return IsIdentifier() || IsProperty();
+  }
+
+  // At the moment PreParser doesn't track these expression types.
+  bool IsFunctionLiteral() const { return false; }
+  bool IsCallNew() const { return false; }
+
+  bool IsNoTemplateTag() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kNoTemplateTagExpression;
+  }
+
+  bool IsSpreadExpression() const {
+    return TypeField::decode(code_) == kSpreadExpression;
+  }
+
+  PreParserExpression AsFunctionLiteral() { return *this; }
+
+  bool IsBinaryOperation() const {
+    return TypeField::decode(code_) == kBinaryOperationExpression;
+  }
+
+  // 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 set_index(int index) {}  // For YieldExpressions
+  void set_should_eager_compile() {}
+
+  int position() const { return RelocInfo::kNoPosition; }
+  void set_function_token_position(int position) {}
+
+  // Parenthesized expressions in the form `( Expression )`.
+  void set_is_parenthesized() {
+    code_ = ParenthesizedField::update(code_, true);
+  }
+  bool is_parenthesized() const { return ParenthesizedField::decode(code_); }
+
+ private:
+  enum Type {
+    kExpression,
+    kIdentifierExpression,
+    kStringLiteralExpression,
+    kBinaryOperationExpression,
+    kSpreadExpression,
+    kObjectLiteralExpression,
+    kArrayLiteralExpression
+  };
+
+  enum ExpressionType {
+    kThisExpression,
+    kThisPropertyExpression,
+    kPropertyExpression,
+    kCallExpression,
+    kSuperCallReference,
+    kNoTemplateTagExpression,
+    kAssignment
+  };
+
+  explicit PreParserExpression(uint32_t expression_code)
+      : code_(expression_code) {}
+
+  // The first three bits are for the Type.
+  typedef BitField<Type, 0, 3> TypeField;
+
+  // The high order bit applies only to nodes which would inherit from the
+  // Expression ASTNode --- This is by necessity, due to the fact that
+  // Expression nodes may be represented as multiple Types, not exclusively
+  // through kExpression.
+  // TODO(caitp, adamk): clean up PreParserExpression bitfields.
+  typedef BitField<bool, 31, 1> ParenthesizedField;
+
+  // The rest of the bits are interpreted depending on the value
+  // of the Type field, so they can share the storage.
+  typedef BitField<ExpressionType, TypeField::kNext, 3> ExpressionTypeField;
+  typedef BitField<bool, TypeField::kNext, 1> IsUseStrictField;
+  typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseStrongField;
+  typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10>
+      IdentifierTypeField;
+  typedef BitField<bool, TypeField::kNext, 1> HasCoverInitializedNameField;
+
+  uint32_t code_;
+};
+
+
+// The pre-parser doesn't need to build lists of expressions, identifiers, or
+// the like.
+template <typename T>
+class PreParserList {
+ public:
+  // These functions make list->Add(some_expression) work (and do nothing).
+  PreParserList() : length_(0) {}
+  PreParserList* operator->() { return this; }
+  void Add(T, void*) { ++length_; }
+  int length() const { return length_; }
+ private:
+  int length_;
+};
+
+
+typedef PreParserList<PreParserExpression> PreParserExpressionList;
+
+
+class PreParserStatement {
+ public:
+  static PreParserStatement Default() {
+    return PreParserStatement(kUnknownStatement);
+  }
+
+  static PreParserStatement Jump() {
+    return PreParserStatement(kJumpStatement);
+  }
+
+  static PreParserStatement FunctionDeclaration() {
+    return PreParserStatement(kFunctionDeclaration);
+  }
+
+  // Creates expression statement from expression.
+  // Preserves being an unparenthesized string literal, possibly
+  // "use strict".
+  static PreParserStatement ExpressionStatement(
+      PreParserExpression expression) {
+    if (expression.IsUseStrictLiteral()) {
+      return PreParserStatement(kUseStrictExpressionStatement);
+    }
+    if (expression.IsUseStrongLiteral()) {
+      return PreParserStatement(kUseStrongExpressionStatement);
+    }
+    if (expression.IsStringLiteral()) {
+      return PreParserStatement(kStringLiteralExpressionStatement);
+    }
+    return Default();
+  }
+
+  bool IsStringLiteral() {
+    return code_ == kStringLiteralExpressionStatement;
+  }
+
+  bool IsUseStrictLiteral() {
+    return code_ == kUseStrictExpressionStatement;
+  }
+
+  bool IsUseStrongLiteral() { return code_ == kUseStrongExpressionStatement; }
+
+  bool IsFunctionDeclaration() {
+    return code_ == kFunctionDeclaration;
+  }
+
+  bool IsJumpStatement() {
+    return code_ == kJumpStatement;
+  }
+
+ private:
+  enum Type {
+    kUnknownStatement,
+    kJumpStatement,
+    kStringLiteralExpressionStatement,
+    kUseStrictExpressionStatement,
+    kUseStrongExpressionStatement,
+    kFunctionDeclaration
+  };
+
+  explicit PreParserStatement(Type code) : code_(code) {}
+  Type code_;
+};
+
+
+typedef PreParserList<PreParserStatement> PreParserStatementList;
+
+
+class PreParserFactory {
+ public:
+  explicit PreParserFactory(void* unused_value_factory) {}
+  PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
+                                       int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewNumberLiteral(double number,
+                                       int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
+                                       int js_flags, int literal_index,
+                                       bool is_strong, int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewArrayLiteral(PreParserExpressionList values,
+                                      int literal_index,
+                                      bool is_strong,
+                                      int pos) {
+    return PreParserExpression::ArrayLiteral();
+  }
+  PreParserExpression NewArrayLiteral(PreParserExpressionList values,
+                                      int first_spread_index, int literal_index,
+                                      bool is_strong, int pos) {
+    return PreParserExpression::ArrayLiteral();
+  }
+  PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
+                                               PreParserExpression value,
+                                               ObjectLiteralProperty::Kind kind,
+                                               bool is_static,
+                                               bool is_computed_name) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
+                                               PreParserExpression value,
+                                               bool is_static,
+                                               bool is_computed_name) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
+                                       int literal_index,
+                                       int boilerplate_properties,
+                                       bool has_function,
+                                       bool is_strong,
+                                       int pos) {
+    return PreParserExpression::ObjectLiteral();
+  }
+  PreParserExpression NewVariableProxy(void* variable) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewProperty(PreParserExpression obj,
+                                  PreParserExpression key,
+                                  int pos) {
+    if (obj.IsThis()) {
+      return PreParserExpression::ThisProperty();
+    }
+    return PreParserExpression::Property();
+  }
+  PreParserExpression NewUnaryOperation(Token::Value op,
+                                        PreParserExpression expression,
+                                        int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewBinaryOperation(Token::Value op,
+                                         PreParserExpression left,
+                                         PreParserExpression right, int pos) {
+    return PreParserExpression::BinaryOperation(left, op, right);
+  }
+  PreParserExpression NewCompareOperation(Token::Value op,
+                                          PreParserExpression left,
+                                          PreParserExpression right, int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewRewritableAssignmentExpression(
+      PreParserExpression expression) {
+    return expression;
+  }
+  PreParserExpression NewAssignment(Token::Value op,
+                                    PreParserExpression left,
+                                    PreParserExpression right,
+                                    int pos) {
+    return PreParserExpression::Assignment();
+  }
+  PreParserExpression NewYield(PreParserExpression generator_object,
+                               PreParserExpression expression,
+                               Yield::Kind yield_kind,
+                               int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewConditional(PreParserExpression condition,
+                                     PreParserExpression then_expression,
+                                     PreParserExpression else_expression,
+                                     int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewCountOperation(Token::Value op,
+                                        bool is_prefix,
+                                        PreParserExpression expression,
+                                        int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewCall(PreParserExpression expression,
+                              PreParserExpressionList arguments,
+                              int pos) {
+    return PreParserExpression::Call();
+  }
+  PreParserExpression NewCallNew(PreParserExpression expression,
+                                 PreParserExpressionList arguments,
+                                 int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewCallRuntime(const AstRawString* name,
+                                     const Runtime::Function* function,
+                                     PreParserExpressionList arguments,
+                                     int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserStatement NewReturnStatement(PreParserExpression expression,
+                                        int pos) {
+    return PreParserStatement::Default();
+  }
+  PreParserExpression NewFunctionLiteral(
+      PreParserIdentifier name, Scope* scope, PreParserStatementList body,
+      int materialized_literal_count, int expected_property_count,
+      int parameter_count,
+      FunctionLiteral::ParameterFlag has_duplicate_parameters,
+      FunctionLiteral::FunctionType function_type,
+      FunctionLiteral::EagerCompileHint eager_compile_hint, FunctionKind kind,
+      int position) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewSpread(PreParserExpression expression, int pos) {
+    return PreParserExpression::Spread(expression);
+  }
+
+  PreParserExpression NewEmptyParentheses(int pos) {
+    return PreParserExpression::Default();
+  }
+
+  // Return the object itself as AstVisitor and implement the needed
+  // dummy method right in this class.
+  PreParserFactory* visitor() { return this; }
+  int* ast_properties() {
+    static int dummy = 42;
+    return &dummy;
+  }
+};
+
+
+struct PreParserFormalParameters : FormalParametersBase {
+  explicit PreParserFormalParameters(Scope* scope)
+      : FormalParametersBase(scope) {}
+  int arity = 0;
+
+  int Arity() const { return arity; }
+  PreParserIdentifier at(int i) { return PreParserIdentifier(); }  // Dummy
+};
+
+
+class PreParser;
+
+class PreParserTraits {
+ public:
+  struct Type {
+    // TODO(marja): To be removed. The Traits object should contain all the data
+    // it needs.
+    typedef PreParser* Parser;
+
+    // PreParser doesn't need to store generator variables.
+    typedef void GeneratorVariable;
+
+    typedef int AstProperties;
+
+    // Return types for traversing functions.
+    typedef PreParserIdentifier Identifier;
+    typedef PreParserExpression Expression;
+    typedef PreParserExpression YieldExpression;
+    typedef PreParserExpression FunctionLiteral;
+    typedef PreParserExpression ClassLiteral;
+    typedef PreParserExpression ObjectLiteralProperty;
+    typedef PreParserExpression Literal;
+    typedef PreParserExpressionList ExpressionList;
+    typedef PreParserExpressionList PropertyList;
+    typedef PreParserIdentifier FormalParameter;
+    typedef PreParserFormalParameters FormalParameters;
+    typedef PreParserStatementList StatementList;
+
+    // For constructing objects returned by the traversing functions.
+    typedef PreParserFactory Factory;
+  };
+
+  explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
+
+  // Helper functions for recursive descent.
+  static bool IsEval(PreParserIdentifier identifier) {
+    return identifier.IsEval();
+  }
+
+  static bool IsArguments(PreParserIdentifier identifier) {
+    return identifier.IsArguments();
+  }
+
+  static bool IsEvalOrArguments(PreParserIdentifier identifier) {
+    return identifier.IsEvalOrArguments();
+  }
+
+  static bool IsUndefined(PreParserIdentifier identifier) {
+    return identifier.IsUndefined();
+  }
+
+  static bool IsPrototype(PreParserIdentifier identifier) {
+    return identifier.IsPrototype();
+  }
+
+  static bool IsConstructor(PreParserIdentifier identifier) {
+    return identifier.IsConstructor();
+  }
+
+  // Returns true if the expression is of type "this.foo".
+  static bool IsThisProperty(PreParserExpression expression) {
+    return expression.IsThisProperty();
+  }
+
+  static bool IsIdentifier(PreParserExpression expression) {
+    return expression.IsIdentifier();
+  }
+
+  static PreParserIdentifier AsIdentifier(PreParserExpression expression) {
+    return expression.AsIdentifier();
+  }
+
+  static bool IsFutureStrictReserved(PreParserIdentifier identifier) {
+    return identifier.IsFutureStrictReserved();
+  }
+
+  static bool IsBoilerplateProperty(PreParserExpression property) {
+    // PreParser doesn't count boilerplate properties.
+    return false;
+  }
+
+  static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
+    return false;
+  }
+
+  static PreParserExpression GetPropertyValue(PreParserExpression property) {
+    return PreParserExpression::Default();
+  }
+
+  // Functions for encapsulating the differences between parsing and preparsing;
+  // operations interleaved with the recursive descent.
+  static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
+    // PreParser should not use FuncNameInferrer.
+    UNREACHABLE();
+  }
+
+  static void PushPropertyName(FuncNameInferrer* fni,
+                               PreParserExpression expression) {
+    // PreParser should not use FuncNameInferrer.
+    UNREACHABLE();
+  }
+
+  static void InferFunctionName(FuncNameInferrer* fni,
+                                PreParserExpression expression) {
+    // PreParser should not use FuncNameInferrer.
+    UNREACHABLE();
+  }
+
+  static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+      Scope* scope, PreParserExpression property, bool* has_function) {}
+
+  static void CheckAssigningFunctionLiteralToProperty(
+      PreParserExpression left, PreParserExpression right) {}
+
+  static PreParserExpression MarkExpressionAsAssigned(
+      PreParserExpression expression) {
+    // TODO(marja): To be able to produce the same errors, the preparser needs
+    // to start tracking which expressions are variables and which are assigned.
+    return expression;
+  }
+
+  bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
+                                              PreParserExpression y,
+                                              Token::Value op,
+                                              int pos,
+                                              PreParserFactory* factory) {
+    return false;
+  }
+
+  PreParserExpression BuildUnaryExpression(PreParserExpression expression,
+                                           Token::Value op, int pos,
+                                           PreParserFactory* factory) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewThrowReferenceError(MessageTemplate::Template message,
+                                             int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewThrowSyntaxError(MessageTemplate::Template message,
+                                          Handle<Object> arg, int pos) {
+    return PreParserExpression::Default();
+  }
+  PreParserExpression NewThrowTypeError(MessageTemplate::Template message,
+                                        Handle<Object> arg, int pos) {
+    return PreParserExpression::Default();
+  }
+
+  // Reporting errors.
+  void ReportMessageAt(Scanner::Location location,
+                       MessageTemplate::Template message,
+                       const char* arg = NULL,
+                       ParseErrorType error_type = kSyntaxError);
+  void ReportMessageAt(int start_pos, int end_pos,
+                       MessageTemplate::Template message,
+                       const char* arg = NULL,
+                       ParseErrorType error_type = kSyntaxError);
+
+  // "null" return type creators.
+  static PreParserIdentifier EmptyIdentifier() {
+    return PreParserIdentifier::Default();
+  }
+  static PreParserIdentifier EmptyIdentifierString() {
+    return PreParserIdentifier::Default();
+  }
+  static PreParserExpression EmptyExpression() {
+    return PreParserExpression::Default();
+  }
+  static PreParserExpression EmptyLiteral() {
+    return PreParserExpression::Default();
+  }
+  static PreParserExpression EmptyObjectLiteralProperty() {
+    return PreParserExpression::Default();
+  }
+  static PreParserExpression EmptyFunctionLiteral() {
+    return PreParserExpression::Default();
+  }
+  static PreParserExpressionList NullExpressionList() {
+    return PreParserExpressionList();
+  }
+
+  // Odd-ball literal creators.
+  static PreParserExpression GetLiteralTheHole(int position,
+                                               PreParserFactory* factory) {
+    return PreParserExpression::Default();
+  }
+
+  // Producing data during the recursive descent.
+  PreParserIdentifier GetSymbol(Scanner* scanner);
+  PreParserIdentifier GetNumberAsSymbol(Scanner* scanner);
+
+  static PreParserIdentifier GetNextSymbol(Scanner* scanner) {
+    return PreParserIdentifier::Default();
+  }
+
+  static PreParserExpression ThisExpression(Scope* scope,
+                                            PreParserFactory* factory,
+                                            int pos) {
+    return PreParserExpression::This();
+  }
+
+  static PreParserExpression SuperPropertyReference(Scope* scope,
+                                                    PreParserFactory* factory,
+                                                    int pos) {
+    return PreParserExpression::Default();
+  }
+
+  static PreParserExpression SuperCallReference(Scope* scope,
+                                                PreParserFactory* factory,
+                                                int pos) {
+    return PreParserExpression::SuperCallReference();
+  }
+
+  static PreParserExpression NewTargetExpression(Scope* scope,
+                                                 PreParserFactory* factory,
+                                                 int pos) {
+    return PreParserExpression::Default();
+  }
+
+  static PreParserExpression DefaultConstructor(bool call_super, Scope* scope,
+                                                int pos, int end_pos) {
+    return PreParserExpression::Default();
+  }
+
+  static PreParserExpression ExpressionFromLiteral(
+      Token::Value token, int pos, Scanner* scanner,
+      PreParserFactory* factory) {
+    return PreParserExpression::Default();
+  }
+
+  static PreParserExpression ExpressionFromIdentifier(
+      PreParserIdentifier name, int start_position, int end_position,
+      Scope* scope, PreParserFactory* factory) {
+    return PreParserExpression::FromIdentifier(name);
+  }
+
+  PreParserExpression ExpressionFromString(int pos,
+                                           Scanner* scanner,
+                                           PreParserFactory* factory = NULL);
+
+  PreParserExpression GetIterator(PreParserExpression iterable,
+                                  PreParserFactory* factory, int pos) {
+    return PreParserExpression::Default();
+  }
+
+  static PreParserExpressionList NewExpressionList(int size, Zone* zone) {
+    return PreParserExpressionList();
+  }
+
+  static PreParserStatementList NewStatementList(int size, Zone* zone) {
+    return PreParserStatementList();
+  }
+
+  static PreParserExpressionList NewPropertyList(int size, Zone* zone) {
+    return PreParserExpressionList();
+  }
+
+  static void AddParameterInitializationBlock(
+      const PreParserFormalParameters& parameters,
+      PreParserStatementList list, bool* ok) {}
+
+  V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count,
+                                      int* expected_property_count, bool* ok) {
+    UNREACHABLE();
+  }
+
+  V8_INLINE PreParserStatementList ParseEagerFunctionBody(
+      PreParserIdentifier function_name, int pos,
+      const PreParserFormalParameters& parameters, FunctionKind kind,
+      FunctionLiteral::FunctionType function_type, bool* ok);
+
+  V8_INLINE void ParseArrowFunctionFormalParameterList(
+      PreParserFormalParameters* parameters,
+      PreParserExpression expression, const Scanner::Location& params_loc,
+      Scanner::Location* duplicate_loc, bool* ok);
+
+  void ReindexLiterals(const PreParserFormalParameters& paramaters) {}
+
+  struct TemplateLiteralState {};
+
+  TemplateLiteralState OpenTemplateLiteral(int pos) {
+    return TemplateLiteralState();
+  }
+  void AddTemplateSpan(TemplateLiteralState*, bool) {}
+  void AddTemplateExpression(TemplateLiteralState*, PreParserExpression) {}
+  PreParserExpression CloseTemplateLiteral(TemplateLiteralState*, int,
+                                           PreParserExpression tag) {
+    if (IsTaggedTemplate(tag)) {
+      // Emulate generation of array literals for tag callsite
+      // 1st is array of cooked strings, second is array of raw strings
+      MaterializeTemplateCallsiteLiterals();
+    }
+    return EmptyExpression();
+  }
+  inline void MaterializeTemplateCallsiteLiterals();
+  PreParserExpression NoTemplateTag() {
+    return PreParserExpression::NoTemplateTag();
+  }
+  static bool IsTaggedTemplate(const PreParserExpression tag) {
+    return !tag.IsNoTemplateTag();
+  }
+
+  void AddFormalParameter(PreParserFormalParameters* parameters,
+                          PreParserExpression pattern,
+                          PreParserExpression initializer,
+                          int initializer_end_position, bool is_rest) {
+    ++parameters->arity;
+  }
+  void DeclareFormalParameter(Scope* scope, PreParserIdentifier parameter,
+                              ExpressionClassifier* classifier) {
+    if (!classifier->is_simple_parameter_list()) {
+      scope->SetHasNonSimpleParameters();
+    }
+  }
+
+  void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}
+
+  // Temporary glue; these functions will move to ParserBase.
+  PreParserExpression ParseV8Intrinsic(bool* ok);
+  V8_INLINE PreParserExpression ParseDoExpression(bool* ok);
+  PreParserExpression ParseFunctionLiteral(
+      PreParserIdentifier name, Scanner::Location function_name_location,
+      FunctionNameValidity function_name_validity, FunctionKind kind,
+      int function_token_position, FunctionLiteral::FunctionType type,
+      FunctionLiteral::ArityRestriction arity_restriction,
+      LanguageMode language_mode, bool* ok);
+
+  PreParserExpression ParseClassLiteral(PreParserIdentifier name,
+                                        Scanner::Location class_name_location,
+                                        bool name_is_strict_reserved, int pos,
+                                        bool* ok);
+
+  PreParserExpressionList PrepareSpreadArguments(PreParserExpressionList list) {
+    return list;
+  }
+
+  inline void MaterializeUnspreadArgumentsLiterals(int count);
+
+  inline PreParserExpression SpreadCall(PreParserExpression function,
+                                        PreParserExpressionList args, int pos);
+
+  inline PreParserExpression SpreadCallNew(PreParserExpression function,
+                                           PreParserExpressionList args,
+                                           int pos);
+
+  inline void RewriteDestructuringAssignments() {}
+
+  inline void QueueDestructuringAssignmentForRewriting(PreParserExpression) {}
+
+  void SetFunctionNameFromPropertyName(PreParserExpression,
+                                       PreParserIdentifier) {}
+  void SetFunctionNameFromIdentifierRef(PreParserExpression,
+                                        PreParserExpression) {}
+
+  inline PreParserExpression RewriteNonPattern(
+      PreParserExpression expr, const ExpressionClassifier* classifier,
+      bool* ok);
+  inline PreParserExpression RewriteNonPatternArguments(
+      PreParserExpression args, const ExpressionClassifier* classifier,
+      bool* ok);
+  inline PreParserExpression RewriteNonPatternObjectLiteralProperty(
+      PreParserExpression property, const ExpressionClassifier* classifier,
+      bool* ok);
+
+ private:
+  PreParser* pre_parser_;
+};
+
+
+// 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<PreParserTraits> {
+ public:
+  typedef PreParserIdentifier Identifier;
+  typedef PreParserExpression Expression;
+  typedef PreParserStatement Statement;
+
+  enum PreParseResult {
+    kPreParseStackOverflow,
+    kPreParseSuccess
+  };
+
+  PreParser(Zone* zone, Scanner* scanner, AstValueFactory* ast_value_factory,
+            ParserRecorder* log, uintptr_t stack_limit)
+      : ParserBase<PreParserTraits>(zone, scanner, stack_limit, NULL,
+                                    ast_value_factory, log, this) {}
+
+  // Pre-parse the program from the character stream; returns true on
+  // success (even if parsing failed, the pre-parse data successfully
+  // captured the syntax error), and false if a stack-overflow happened
+  // during parsing.
+  PreParseResult PreParseProgram(int* materialized_literals = 0) {
+    Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
+    PreParserFactory factory(NULL);
+    FunctionState top_scope(&function_state_, &scope_, scope, kNormalFunction,
+                            &factory);
+    bool ok = true;
+    int start_position = scanner()->peek_location().beg_pos;
+    ParseStatementList(Token::EOS, &ok);
+    if (stack_overflow()) return kPreParseStackOverflow;
+    if (!ok) {
+      ReportUnexpectedToken(scanner()->current_token());
+    } else if (is_strict(scope_->language_mode())) {
+      CheckStrictOctalLiteral(start_position, scanner()->location().end_pos,
+                              &ok);
+    }
+    if (materialized_literals) {
+      *materialized_literals = function_state_->materialized_literal_count();
+    }
+    return kPreParseSuccess;
+  }
+
+  // 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 PreParseLazyFunction(
+      LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
+      ParserRecorder* log, Scanner::BookmarkScope* bookmark = nullptr);
+
+ private:
+  friend class PreParserTraits;
+
+  static const int kLazyParseTrialLimit = 200;
+
+  // 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.
+  Statement ParseStatementListItem(bool* ok);
+  void ParseStatementList(int end_token, bool* ok,
+                          Scanner::BookmarkScope* bookmark = nullptr);
+  Statement ParseStatement(bool* ok);
+  Statement ParseSubStatement(bool* ok);
+  Statement ParseFunctionDeclaration(bool* ok);
+  Statement ParseClassDeclaration(bool* ok);
+  Statement ParseBlock(bool* ok);
+  Statement ParseVariableStatement(VariableDeclarationContext var_context,
+                                   bool* ok);
+  Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
+                                      int* num_decl, bool* is_lexical,
+                                      bool* is_binding_pattern,
+                                      Scanner::Location* first_initializer_loc,
+                                      Scanner::Location* bindings_loc,
+                                      bool* ok);
+  Statement ParseExpressionOrLabelledStatement(bool* ok);
+  Statement ParseIfStatement(bool* ok);
+  Statement ParseContinueStatement(bool* ok);
+  Statement ParseBreakStatement(bool* ok);
+  Statement ParseReturnStatement(bool* ok);
+  Statement ParseWithStatement(bool* ok);
+  Statement ParseSwitchStatement(bool* ok);
+  Statement ParseDoWhileStatement(bool* ok);
+  Statement ParseWhileStatement(bool* ok);
+  Statement ParseForStatement(bool* ok);
+  Statement ParseThrowStatement(bool* ok);
+  Statement ParseTryStatement(bool* ok);
+  Statement ParseDebuggerStatement(bool* ok);
+  Expression ParseConditionalExpression(bool accept_IN, bool* ok);
+  Expression ParseObjectLiteral(bool* ok);
+  Expression ParseV8Intrinsic(bool* ok);
+  Expression ParseDoExpression(bool* ok);
+
+  V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count,
+                                      int* expected_property_count, bool* ok);
+  V8_INLINE PreParserStatementList ParseEagerFunctionBody(
+      PreParserIdentifier function_name, int pos,
+      const PreParserFormalParameters& parameters, FunctionKind kind,
+      FunctionLiteral::FunctionType function_type, bool* ok);
+
+  Expression ParseFunctionLiteral(
+      Identifier name, Scanner::Location function_name_location,
+      FunctionNameValidity function_name_validity, FunctionKind kind,
+      int function_token_pos, FunctionLiteral::FunctionType function_type,
+      FunctionLiteral::ArityRestriction arity_restriction,
+      LanguageMode language_mode, bool* ok);
+  void ParseLazyFunctionLiteralBody(bool* ok,
+                                    Scanner::BookmarkScope* bookmark = nullptr);
+
+  PreParserExpression ParseClassLiteral(PreParserIdentifier name,
+                                        Scanner::Location class_name_location,
+                                        bool name_is_strict_reserved, int pos,
+                                        bool* ok);
+};
+
+
+void PreParserTraits::MaterializeTemplateCallsiteLiterals() {
+  pre_parser_->function_state_->NextMaterializedLiteralIndex();
+  pre_parser_->function_state_->NextMaterializedLiteralIndex();
+}
+
+
+void PreParserTraits::MaterializeUnspreadArgumentsLiterals(int count) {
+  for (int i = 0; i < count; ++i) {
+    pre_parser_->function_state_->NextMaterializedLiteralIndex();
+  }
+}
+
+
+PreParserExpression PreParserTraits::SpreadCall(PreParserExpression function,
+                                                PreParserExpressionList args,
+                                                int pos) {
+  return pre_parser_->factory()->NewCall(function, args, pos);
+}
+
+PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
+                                                   PreParserExpressionList args,
+                                                   int pos) {
+  return pre_parser_->factory()->NewCallNew(function, args, pos);
+}
+
+
+void PreParserTraits::ParseArrowFunctionFormalParameterList(
+    PreParserFormalParameters* parameters,
+    PreParserExpression params, const Scanner::Location& params_loc,
+    Scanner::Location* duplicate_loc, bool* ok) {
+  // TODO(wingo): Detect duplicated identifiers in paramlists.  Detect parameter
+  // lists that are too long.
+}
+
+
+PreParserExpression PreParserTraits::ParseDoExpression(bool* ok) {
+  return pre_parser_->ParseDoExpression(ok);
+}
+
+
+PreParserExpression PreParserTraits::RewriteNonPattern(
+    PreParserExpression expr, const ExpressionClassifier* classifier,
+    bool* ok) {
+  pre_parser_->ValidateExpression(classifier, ok);
+  return expr;
+}
+
+
+PreParserExpression PreParserTraits::RewriteNonPatternArguments(
+    PreParserExpression args, const ExpressionClassifier* classifier,
+    bool* ok) {
+  pre_parser_->ValidateExpression(classifier, ok);
+  return args;
+}
+
+
+PreParserExpression PreParserTraits::RewriteNonPatternObjectLiteralProperty(
+    PreParserExpression property, const ExpressionClassifier* classifier,
+    bool* ok) {
+  pre_parser_->ValidateExpression(classifier, ok);
+  return property;
+}
+
+
+PreParserStatementList PreParser::ParseEagerFunctionBody(
+    PreParserIdentifier function_name, int pos,
+    const PreParserFormalParameters& parameters, FunctionKind kind,
+    FunctionLiteral::FunctionType function_type, bool* ok) {
+  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
+
+  ParseStatementList(Token::RBRACE, ok);
+  if (!*ok) return PreParserStatementList();
+
+  Expect(Token::RBRACE, ok);
+  return PreParserStatementList();
+}
+
+
+PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
+    PreParserIdentifier function_name, int pos,
+    const PreParserFormalParameters& parameters, FunctionKind kind,
+    FunctionLiteral::FunctionType function_type, bool* ok) {
+  return pre_parser_->ParseEagerFunctionBody(function_name, pos, parameters,
+                                             kind, function_type, ok);
+}
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_PREPARSER_H
diff --git a/src/parsing/rewriter.cc b/src/parsing/rewriter.cc
new file mode 100644
index 0000000..4da60ac
--- /dev/null
+++ b/src/parsing/rewriter.cc
@@ -0,0 +1,403 @@
+// 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.
+
+#include "src/parsing/rewriter.h"
+
+#include "src/ast/ast.h"
+#include "src/ast/scopes.h"
+#include "src/parsing/parser.h"
+
+namespace v8 {
+namespace internal {
+
+class Processor: public AstVisitor {
+ public:
+  Processor(Isolate* isolate, Scope* scope, Variable* result,
+            AstValueFactory* ast_value_factory)
+      : result_(result),
+        result_assigned_(false),
+        replacement_(nullptr),
+        is_set_(false),
+        zone_(ast_value_factory->zone()),
+        scope_(scope),
+        factory_(ast_value_factory) {
+    InitializeAstVisitor(isolate);
+  }
+
+  Processor(Parser* parser, Scope* scope, Variable* result,
+            AstValueFactory* ast_value_factory)
+      : result_(result),
+        result_assigned_(false),
+        replacement_(nullptr),
+        is_set_(false),
+        scope_(scope),
+        factory_(ast_value_factory) {
+    InitializeAstVisitor(parser->stack_limit());
+  }
+
+  ~Processor() override {}
+
+  void Process(ZoneList<Statement*>* statements);
+  bool result_assigned() const { return result_assigned_; }
+
+  Zone* zone() { return zone_; }
+  Scope* scope() { return scope_; }
+  AstNodeFactory* factory() { return &factory_; }
+
+  // Returns ".result = value"
+  Expression* SetResult(Expression* value) {
+    result_assigned_ = true;
+    VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
+    return factory()->NewAssignment(Token::ASSIGN, result_proxy, value,
+                                    RelocInfo::kNoPosition);
+  }
+
+  // Inserts '.result = undefined' in front of the given statement.
+  Statement* AssignUndefinedBefore(Statement* s);
+
+ private:
+  Variable* result_;
+
+  // We are not tracking result usage via the result_'s use
+  // counts (we leave the accurate computation to the
+  // usage analyzer). Instead we simple remember if
+  // there was ever an assignment to result_.
+  bool result_assigned_;
+
+  // When visiting a node, we "return" a replacement for that node in
+  // [replacement_].  In many cases this will just be the original node.
+  Statement* replacement_;
+
+  // To avoid storing to .result all the time, we eliminate some of
+  // the stores by keeping track of whether or not we're sure .result
+  // will be overwritten anyway. This is a bit more tricky than what I
+  // was hoping for.
+  bool is_set_;
+
+  Zone* zone_;
+  Scope* scope_;
+  AstNodeFactory factory_;
+
+  // Node visitors.
+#define DEF_VISIT(type) void Visit##type(type* node) override;
+  AST_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+  void VisitIterationStatement(IterationStatement* stmt);
+
+  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
+};
+
+
+Statement* Processor::AssignUndefinedBefore(Statement* s) {
+  Expression* result_proxy = factory()->NewVariableProxy(result_);
+  Expression* undef = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
+  Expression* assignment = factory()->NewAssignment(
+      Token::ASSIGN, result_proxy, undef, RelocInfo::kNoPosition);
+  Block* b = factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
+  b->statements()->Add(
+      factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
+      zone());
+  b->statements()->Add(s, zone());
+  return b;
+}
+
+
+void Processor::Process(ZoneList<Statement*>* statements) {
+  for (int i = statements->length() - 1; i >= 0; --i) {
+    Visit(statements->at(i));
+    statements->Set(i, replacement_);
+  }
+}
+
+
+void Processor::VisitBlock(Block* node) {
+  // An initializer block is the rewritten form of a variable declaration
+  // with initialization expressions. The initializer block contains the
+  // list of assignments corresponding to the initialization expressions.
+  // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of
+  // a variable declaration with initialization expression is 'undefined'
+  // with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
+  // returns 'undefined'. To obtain the same behavior with v8, we need
+  // to prevent rewriting in that case.
+  if (!node->ignore_completion_value()) Process(node->statements());
+  replacement_ = node;
+}
+
+
+void Processor::VisitExpressionStatement(ExpressionStatement* node) {
+  // Rewrite : <x>; -> .result = <x>;
+  if (!is_set_) {
+    node->set_expression(SetResult(node->expression()));
+    is_set_ = true;
+  }
+  replacement_ = node;
+}
+
+
+void Processor::VisitIfStatement(IfStatement* node) {
+  // Rewrite both branches.
+  bool set_after = is_set_;
+  Visit(node->then_statement());
+  node->set_then_statement(replacement_);
+  bool set_in_then = is_set_;
+  is_set_ = set_after;
+  Visit(node->else_statement());
+  node->set_else_statement(replacement_);
+  is_set_ = is_set_ && set_in_then;
+  replacement_ = node;
+
+  if (FLAG_harmony_completion && !is_set_) {
+    is_set_ = true;
+    replacement_ = AssignUndefinedBefore(node);
+  }
+}
+
+
+void Processor::VisitIterationStatement(IterationStatement* node) {
+  // Rewrite the body.
+  bool set_after = is_set_;
+  is_set_ = false;  // We are in a loop, so we can't rely on [set_after].
+  Visit(node->body());
+  node->set_body(replacement_);
+  is_set_ = is_set_ && set_after;
+  replacement_ = node;
+
+  if (FLAG_harmony_completion && !is_set_) {
+    is_set_ = true;
+    replacement_ = AssignUndefinedBefore(node);
+  }
+}
+
+
+void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
+  VisitIterationStatement(node);
+}
+
+
+void Processor::VisitWhileStatement(WhileStatement* node) {
+  VisitIterationStatement(node);
+}
+
+
+void Processor::VisitForStatement(ForStatement* node) {
+  VisitIterationStatement(node);
+}
+
+
+void Processor::VisitForInStatement(ForInStatement* node) {
+  VisitIterationStatement(node);
+}
+
+
+void Processor::VisitForOfStatement(ForOfStatement* node) {
+  VisitIterationStatement(node);
+}
+
+
+void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
+  // Rewrite both try and catch block.
+  bool set_after = is_set_;
+  Visit(node->try_block());
+  node->set_try_block(static_cast<Block*>(replacement_));
+  bool set_in_try = is_set_;
+  is_set_ = set_after;
+  Visit(node->catch_block());
+  node->set_catch_block(static_cast<Block*>(replacement_));
+  is_set_ = is_set_ && set_in_try;
+  replacement_ = node;
+
+  if (FLAG_harmony_completion && !is_set_) {
+    is_set_ = true;
+    replacement_ = AssignUndefinedBefore(node);
+  }
+}
+
+
+void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
+  // Rewrite both try and finally block (in reverse order).
+  bool set_after = is_set_;
+  is_set_ = true;  // Don't normally need to assign in finally block.
+  Visit(node->finally_block());
+  node->set_finally_block(replacement_->AsBlock());
+  {  // Save .result value at the beginning of the finally block and restore it
+     // at the end again: ".backup = .result; ...; .result = .backup"
+     // This is necessary because the finally block does not normally contribute
+     // to the completion value.
+    Variable* backup = scope()->NewTemporary(
+        factory()->ast_value_factory()->dot_result_string());
+    Expression* backup_proxy = factory()->NewVariableProxy(backup);
+    Expression* result_proxy = factory()->NewVariableProxy(result_);
+    Expression* save = factory()->NewAssignment(
+        Token::ASSIGN, backup_proxy, result_proxy, RelocInfo::kNoPosition);
+    Expression* restore = factory()->NewAssignment(
+        Token::ASSIGN, result_proxy, backup_proxy, RelocInfo::kNoPosition);
+    node->finally_block()->statements()->InsertAt(
+        0, factory()->NewExpressionStatement(save, RelocInfo::kNoPosition),
+        zone());
+    node->finally_block()->statements()->Add(
+        factory()->NewExpressionStatement(restore, RelocInfo::kNoPosition),
+        zone());
+  }
+  is_set_ = set_after;
+  Visit(node->try_block());
+  node->set_try_block(replacement_->AsBlock());
+  replacement_ = node;
+
+  if (FLAG_harmony_completion && !is_set_) {
+    is_set_ = true;
+    replacement_ = AssignUndefinedBefore(node);
+  }
+}
+
+
+void Processor::VisitSwitchStatement(SwitchStatement* node) {
+  // Rewrite statements in all case clauses (in reverse order).
+  ZoneList<CaseClause*>* clauses = node->cases();
+  bool set_after = is_set_;
+  for (int i = clauses->length() - 1; i >= 0; --i) {
+    CaseClause* clause = clauses->at(i);
+    Process(clause->statements());
+  }
+  is_set_ = is_set_ && set_after;
+  replacement_ = node;
+
+  if (FLAG_harmony_completion && !is_set_) {
+    is_set_ = true;
+    replacement_ = AssignUndefinedBefore(node);
+  }
+}
+
+
+void Processor::VisitContinueStatement(ContinueStatement* node) {
+  is_set_ = false;
+  replacement_ = node;
+}
+
+
+void Processor::VisitBreakStatement(BreakStatement* node) {
+  is_set_ = false;
+  replacement_ = node;
+}
+
+
+void Processor::VisitWithStatement(WithStatement* node) {
+  Visit(node->statement());
+  node->set_statement(replacement_);
+  replacement_ = node;
+
+  if (FLAG_harmony_completion && !is_set_) {
+    is_set_ = true;
+    replacement_ = AssignUndefinedBefore(node);
+  }
+}
+
+
+void Processor::VisitSloppyBlockFunctionStatement(
+    SloppyBlockFunctionStatement* node) {
+  Visit(node->statement());
+  node->set_statement(replacement_);
+  replacement_ = node;
+}
+
+
+void Processor::VisitEmptyStatement(EmptyStatement* node) {
+  replacement_ = node;
+}
+
+
+void Processor::VisitReturnStatement(ReturnStatement* node) {
+  is_set_ = true;
+  replacement_ = node;
+}
+
+
+void Processor::VisitDebuggerStatement(DebuggerStatement* node) {
+  replacement_ = node;
+}
+
+
+// Expressions are never visited.
+#define DEF_VISIT(type)                                         \
+  void Processor::Visit##type(type* expr) { UNREACHABLE(); }
+EXPRESSION_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+
+// Declarations are never visited.
+#define DEF_VISIT(type) \
+  void Processor::Visit##type(type* expr) { UNREACHABLE(); }
+DECLARATION_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+
+// Assumes code has been parsed.  Mutates the AST, so the AST should not
+// continue to be used in the case of failure.
+bool Rewriter::Rewrite(ParseInfo* info) {
+  FunctionLiteral* function = info->literal();
+  DCHECK(function != NULL);
+  Scope* scope = function->scope();
+  DCHECK(scope != NULL);
+  if (!scope->is_script_scope() && !scope->is_eval_scope()) return true;
+
+  ZoneList<Statement*>* body = function->body();
+  if (!body->is_empty()) {
+    Variable* result =
+        scope->NewTemporary(info->ast_value_factory()->dot_result_string());
+    // The name string must be internalized at this point.
+    DCHECK(!result->name().is_null());
+    Processor processor(info->isolate(), scope, result,
+                        info->ast_value_factory());
+    processor.Process(body);
+    if (processor.HasStackOverflow()) return false;
+
+    if (processor.result_assigned()) {
+      DCHECK(function->end_position() != RelocInfo::kNoPosition);
+      // Set the position of the assignment statement one character past the
+      // source code, such that it definitely is not in the source code range
+      // of an immediate inner scope. For example in
+      //   eval('with ({x:1}) x = 1');
+      // the end position of the function generated for executing the eval code
+      // coincides with the end of the with scope which is the position of '1'.
+      int pos = function->end_position();
+      VariableProxy* result_proxy =
+          processor.factory()->NewVariableProxy(result, pos);
+      Statement* result_statement =
+          processor.factory()->NewReturnStatement(result_proxy, pos);
+      body->Add(result_statement, info->zone());
+    }
+  }
+
+  return true;
+}
+
+
+bool Rewriter::Rewrite(Parser* parser, DoExpression* expr,
+                       AstValueFactory* factory) {
+  Block* block = expr->block();
+  Scope* scope = block->scope();
+  ZoneList<Statement*>* body = block->statements();
+  VariableProxy* result = expr->result();
+  Variable* result_var = result->var();
+
+  if (!body->is_empty()) {
+    Processor processor(parser, scope, result_var, factory);
+    processor.Process(body);
+    if (processor.HasStackOverflow()) return false;
+
+    if (!processor.result_assigned()) {
+      AstNodeFactory* node_factory = processor.factory();
+      Expression* undef =
+          node_factory->NewUndefinedLiteral(RelocInfo::kNoPosition);
+      Statement* completion = node_factory->NewExpressionStatement(
+          processor.SetResult(undef), expr->position());
+      body->Add(completion, factory->zone());
+    }
+  }
+  return true;
+}
+
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/rewriter.h b/src/parsing/rewriter.h
new file mode 100644
index 0000000..477644a
--- /dev/null
+++ b/src/parsing/rewriter.h
@@ -0,0 +1,36 @@
+// Copyright 2011 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_REWRITER_H_
+#define V8_PARSING_REWRITER_H_
+
+namespace v8 {
+namespace internal {
+
+class AstValueFactory;
+class DoExpression;
+class ParseInfo;
+class Parser;
+
+class Rewriter {
+ public:
+  // Rewrite top-level code (ECMA 262 "programs") so as to conservatively
+  // include an assignment of the value of the last statement in the code to
+  // a compiler-generated temporary variable wherever needed.
+  //
+  // Assumes code has been parsed and scopes have been analyzed.  Mutates the
+  // AST, so the AST should not continue to be used in the case of failure.
+  static bool Rewrite(ParseInfo* info);
+
+  // Rewrite a list of statements, using the same rules as a top-level program,
+  // to  ensure identical behaviour of completion result.
+  static bool Rewrite(Parser* parser, DoExpression* expr,
+                      AstValueFactory* factory);
+};
+
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_REWRITER_H_
diff --git a/src/parsing/scanner-character-streams.cc b/src/parsing/scanner-character-streams.cc
new file mode 100644
index 0000000..91ed54f
--- /dev/null
+++ b/src/parsing/scanner-character-streams.cc
@@ -0,0 +1,589 @@
+// Copyright 2011 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.
+
+#include "src/parsing/scanner-character-streams.h"
+
+#include "include/v8.h"
+#include "src/globals.h"
+#include "src/handles.h"
+#include "src/list-inl.h"  // TODO(mstarzinger): Temporary cycle breaker!
+#include "src/objects.h"
+#include "src/unicode-inl.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+size_t CopyCharsHelper(uint16_t* dest, size_t length, const uint8_t* src,
+                       size_t* src_pos, size_t src_length,
+                       ScriptCompiler::StreamedSource::Encoding encoding) {
+  // It's possible that this will be called with length 0, but don't assume that
+  // the functions this calls handle it gracefully.
+  if (length == 0) return 0;
+
+  if (encoding == ScriptCompiler::StreamedSource::UTF8) {
+    return v8::internal::Utf8ToUtf16CharacterStream::CopyChars(
+        dest, length, src, src_pos, src_length);
+  }
+
+  size_t to_fill = length;
+  if (to_fill > src_length - *src_pos) to_fill = src_length - *src_pos;
+
+  if (encoding == ScriptCompiler::StreamedSource::ONE_BYTE) {
+    v8::internal::CopyChars<uint8_t, uint16_t>(dest, src + *src_pos, to_fill);
+  } else {
+    DCHECK(encoding == ScriptCompiler::StreamedSource::TWO_BYTE);
+    v8::internal::CopyChars<uint16_t, uint16_t>(
+        dest, reinterpret_cast<const uint16_t*>(src + *src_pos), to_fill);
+  }
+  *src_pos += to_fill;
+  return to_fill;
+}
+
+}  // namespace
+
+
+// ----------------------------------------------------------------------------
+// BufferedUtf16CharacterStreams
+
+BufferedUtf16CharacterStream::BufferedUtf16CharacterStream()
+    : Utf16CharacterStream(),
+      pushback_limit_(NULL) {
+  // Initialize buffer as being empty. First read will fill the buffer.
+  buffer_cursor_ = buffer_;
+  buffer_end_ = buffer_;
+}
+
+
+BufferedUtf16CharacterStream::~BufferedUtf16CharacterStream() { }
+
+void BufferedUtf16CharacterStream::PushBack(uc32 character) {
+  if (character == kEndOfInput) {
+    pos_--;
+    return;
+  }
+  if (pushback_limit_ == NULL && buffer_cursor_ > buffer_) {
+    // buffer_ is writable, buffer_cursor_ is const pointer.
+    buffer_[--buffer_cursor_ - buffer_] = static_cast<uc16>(character);
+    pos_--;
+    return;
+  }
+  SlowPushBack(static_cast<uc16>(character));
+}
+
+
+void BufferedUtf16CharacterStream::SlowPushBack(uc16 character) {
+  // In pushback mode, the end of the buffer contains pushback,
+  // and the start of the buffer (from buffer start to pushback_limit_)
+  // contains valid data that comes just after the pushback.
+  // We NULL the pushback_limit_ if pushing all the way back to the
+  // start of the buffer.
+
+  if (pushback_limit_ == NULL) {
+    // Enter pushback mode.
+    pushback_limit_ = buffer_end_;
+    buffer_end_ = buffer_ + kBufferSize;
+    buffer_cursor_ = buffer_end_;
+  }
+  // Ensure that there is room for at least one pushback.
+  DCHECK(buffer_cursor_ > buffer_);
+  DCHECK(pos_ > 0);
+  buffer_[--buffer_cursor_ - buffer_] = character;
+  if (buffer_cursor_ == buffer_) {
+    pushback_limit_ = NULL;
+  } else if (buffer_cursor_ < pushback_limit_) {
+    pushback_limit_ = buffer_cursor_;
+  }
+  pos_--;
+}
+
+
+bool BufferedUtf16CharacterStream::ReadBlock() {
+  buffer_cursor_ = buffer_;
+  if (pushback_limit_ != NULL) {
+    // Leave pushback mode.
+    buffer_end_ = pushback_limit_;
+    pushback_limit_ = NULL;
+    // If there were any valid characters left at the
+    // start of the buffer, use those.
+    if (buffer_cursor_ < buffer_end_) return true;
+    // Otherwise read a new block.
+  }
+  size_t length = FillBuffer(pos_);
+  buffer_end_ = buffer_ + length;
+  return length > 0;
+}
+
+
+size_t BufferedUtf16CharacterStream::SlowSeekForward(size_t delta) {
+  // Leave pushback mode (i.e., ignore that there might be valid data
+  // in the buffer before the pushback_limit_ point).
+  pushback_limit_ = NULL;
+  return BufferSeekForward(delta);
+}
+
+
+// ----------------------------------------------------------------------------
+// GenericStringUtf16CharacterStream
+
+
+GenericStringUtf16CharacterStream::GenericStringUtf16CharacterStream(
+    Handle<String> data, size_t start_position, size_t end_position)
+    : string_(data), length_(end_position), bookmark_(kNoBookmark) {
+  DCHECK(end_position >= start_position);
+  pos_ = start_position;
+}
+
+
+GenericStringUtf16CharacterStream::~GenericStringUtf16CharacterStream() { }
+
+
+bool GenericStringUtf16CharacterStream::SetBookmark() {
+  bookmark_ = pos_;
+  return true;
+}
+
+
+void GenericStringUtf16CharacterStream::ResetToBookmark() {
+  DCHECK(bookmark_ != kNoBookmark);
+  pos_ = bookmark_;
+  buffer_cursor_ = buffer_;
+  buffer_end_ = buffer_ + FillBuffer(pos_);
+}
+
+
+size_t GenericStringUtf16CharacterStream::BufferSeekForward(size_t delta) {
+  size_t old_pos = pos_;
+  pos_ = Min(pos_ + delta, length_);
+  ReadBlock();
+  return pos_ - old_pos;
+}
+
+
+size_t GenericStringUtf16CharacterStream::FillBuffer(size_t from_pos) {
+  if (from_pos >= length_) return 0;
+  size_t length = kBufferSize;
+  if (from_pos + length > length_) {
+    length = length_ - from_pos;
+  }
+  String::WriteToFlat<uc16>(*string_, buffer_, static_cast<int>(from_pos),
+                            static_cast<int>(from_pos + length));
+  return length;
+}
+
+
+// ----------------------------------------------------------------------------
+// Utf8ToUtf16CharacterStream
+Utf8ToUtf16CharacterStream::Utf8ToUtf16CharacterStream(const byte* data,
+                                                       size_t length)
+    : BufferedUtf16CharacterStream(),
+      raw_data_(data),
+      raw_data_length_(length),
+      raw_data_pos_(0),
+      raw_character_position_(0) {
+  ReadBlock();
+}
+
+
+Utf8ToUtf16CharacterStream::~Utf8ToUtf16CharacterStream() { }
+
+
+size_t Utf8ToUtf16CharacterStream::CopyChars(uint16_t* dest, size_t length,
+                                             const byte* src, size_t* src_pos,
+                                             size_t src_length) {
+  static const unibrow::uchar kMaxUtf16Character =
+      unibrow::Utf16::kMaxNonSurrogateCharCode;
+  size_t i = 0;
+  // Because of the UTF-16 lead and trail surrogates, we stop filling the buffer
+  // one character early (in the normal case), because we need to have at least
+  // two free spaces in the buffer to be sure that the next character will fit.
+  while (i < length - 1) {
+    if (*src_pos == src_length) break;
+    unibrow::uchar c = src[*src_pos];
+    if (c <= unibrow::Utf8::kMaxOneByteChar) {
+      *src_pos = *src_pos + 1;
+    } else {
+      c = unibrow::Utf8::CalculateValue(src + *src_pos, src_length - *src_pos,
+                                        src_pos);
+    }
+    if (c > kMaxUtf16Character) {
+      dest[i++] = unibrow::Utf16::LeadSurrogate(c);
+      dest[i++] = unibrow::Utf16::TrailSurrogate(c);
+    } else {
+      dest[i++] = static_cast<uc16>(c);
+    }
+  }
+  return i;
+}
+
+
+size_t Utf8ToUtf16CharacterStream::BufferSeekForward(size_t delta) {
+  size_t old_pos = pos_;
+  size_t target_pos = pos_ + delta;
+  SetRawPosition(target_pos);
+  pos_ = raw_character_position_;
+  ReadBlock();
+  return pos_ - old_pos;
+}
+
+
+size_t Utf8ToUtf16CharacterStream::FillBuffer(size_t char_position) {
+  SetRawPosition(char_position);
+  if (raw_character_position_ != char_position) {
+    // char_position was not a valid position in the stream (hit the end
+    // while spooling to it).
+    return 0u;
+  }
+  size_t i = CopyChars(buffer_, kBufferSize, raw_data_, &raw_data_pos_,
+                       raw_data_length_);
+  raw_character_position_ = char_position + i;
+  return i;
+}
+
+
+static const byte kUtf8MultiByteMask = 0xC0;
+static const byte kUtf8MultiByteCharFollower = 0x80;
+
+
+#ifdef DEBUG
+static const byte kUtf8MultiByteCharStart = 0xC0;
+static bool IsUtf8MultiCharacterStart(byte first_byte) {
+  return (first_byte & kUtf8MultiByteMask) == kUtf8MultiByteCharStart;
+}
+#endif
+
+
+static bool IsUtf8MultiCharacterFollower(byte later_byte) {
+  return (later_byte & kUtf8MultiByteMask) == kUtf8MultiByteCharFollower;
+}
+
+
+// Move the cursor back to point at the preceding UTF-8 character start
+// in the buffer.
+static inline void Utf8CharacterBack(const byte* buffer, size_t* cursor) {
+  byte character = buffer[--*cursor];
+  if (character > unibrow::Utf8::kMaxOneByteChar) {
+    DCHECK(IsUtf8MultiCharacterFollower(character));
+    // Last byte of a multi-byte character encoding. Step backwards until
+    // pointing to the first byte of the encoding, recognized by having the
+    // top two bits set.
+    while (IsUtf8MultiCharacterFollower(buffer[--*cursor])) { }
+    DCHECK(IsUtf8MultiCharacterStart(buffer[*cursor]));
+  }
+}
+
+
+// Move the cursor forward to point at the next following UTF-8 character start
+// in the buffer.
+static inline void Utf8CharacterForward(const byte* buffer, size_t* cursor) {
+  byte character = buffer[(*cursor)++];
+  if (character > unibrow::Utf8::kMaxOneByteChar) {
+    // First character of a multi-byte character encoding.
+    // The number of most-significant one-bits determines the length of the
+    // encoding:
+    //  110..... - (0xCx, 0xDx) one additional byte (minimum).
+    //  1110.... - (0xEx) two additional bytes.
+    //  11110... - (0xFx) three additional bytes (maximum).
+    DCHECK(IsUtf8MultiCharacterStart(character));
+    // Additional bytes is:
+    // 1 if value in range 0xC0 .. 0xDF.
+    // 2 if value in range 0xE0 .. 0xEF.
+    // 3 if value in range 0xF0 .. 0xF7.
+    // Encode that in a single value.
+    size_t additional_bytes =
+        ((0x3211u) >> (((character - 0xC0) >> 2) & 0xC)) & 0x03;
+    *cursor += additional_bytes;
+    DCHECK(!IsUtf8MultiCharacterFollower(buffer[1 + additional_bytes]));
+  }
+}
+
+
+// This can't set a raw position between two surrogate pairs, since there
+// is no position in the UTF8 stream that corresponds to that.  This assumes
+// that the surrogate pair is correctly coded as a 4 byte UTF-8 sequence.  If
+// it is illegally coded as two 3 byte sequences then there is no problem here.
+void Utf8ToUtf16CharacterStream::SetRawPosition(size_t target_position) {
+  if (raw_character_position_ > target_position) {
+    // Spool backwards in utf8 buffer.
+    do {
+      size_t old_pos = raw_data_pos_;
+      Utf8CharacterBack(raw_data_, &raw_data_pos_);
+      raw_character_position_--;
+      DCHECK(old_pos - raw_data_pos_ <= 4);
+      // Step back over both code units for surrogate pairs.
+      if (old_pos - raw_data_pos_ == 4) raw_character_position_--;
+    } while (raw_character_position_ > target_position);
+    // No surrogate pair splitting.
+    DCHECK(raw_character_position_ == target_position);
+    return;
+  }
+  // Spool forwards in the utf8 buffer.
+  while (raw_character_position_ < target_position) {
+    if (raw_data_pos_ == raw_data_length_) return;
+    size_t old_pos = raw_data_pos_;
+    Utf8CharacterForward(raw_data_, &raw_data_pos_);
+    raw_character_position_++;
+    DCHECK(raw_data_pos_ - old_pos <= 4);
+    if (raw_data_pos_ - old_pos == 4) raw_character_position_++;
+  }
+  // No surrogate pair splitting.
+  DCHECK(raw_character_position_ == target_position);
+}
+
+
+size_t ExternalStreamingStream::FillBuffer(size_t position) {
+  // Ignore "position" which is the position in the decoded data. Instead,
+  // ExternalStreamingStream keeps track of the position in the raw data.
+  size_t data_in_buffer = 0;
+  // Note that the UTF-8 decoder might not be able to fill the buffer
+  // completely; it will typically leave the last character empty (see
+  // Utf8ToUtf16CharacterStream::CopyChars).
+  while (data_in_buffer < kBufferSize - 1) {
+    if (current_data_ == NULL) {
+      // GetSomeData will wait until the embedder has enough data. Here's an
+      // interface between the API which uses size_t (which is the correct type
+      // here) and the internal parts which use size_t.
+      current_data_length_ = source_stream_->GetMoreData(&current_data_);
+      current_data_offset_ = 0;
+      bool data_ends = current_data_length_ == 0;
+      bookmark_data_is_from_current_data_ = false;
+
+      // A caveat: a data chunk might end with bytes from an incomplete UTF-8
+      // character (the rest of the bytes will be in the next chunk).
+      if (encoding_ == ScriptCompiler::StreamedSource::UTF8) {
+        HandleUtf8SplitCharacters(&data_in_buffer);
+        if (!data_ends && current_data_offset_ == current_data_length_) {
+          // The data stream didn't end, but we used all the data in the
+          // chunk. This will only happen when the chunk was really small. We
+          // don't handle the case where a UTF-8 character is split over several
+          // chunks; in that case V8 won't crash, but it will be a parse error.
+          FlushCurrent();
+          continue;  // Request a new chunk.
+        }
+      }
+
+      // Did the data stream end?
+      if (data_ends) {
+        DCHECK(utf8_split_char_buffer_length_ == 0);
+        return data_in_buffer;
+      }
+    }
+
+    // Fill the buffer from current_data_.
+    size_t new_offset = 0;
+    size_t new_chars_in_buffer =
+        CopyCharsHelper(buffer_ + data_in_buffer, kBufferSize - data_in_buffer,
+                        current_data_ + current_data_offset_, &new_offset,
+                        current_data_length_ - current_data_offset_, encoding_);
+    data_in_buffer += new_chars_in_buffer;
+    current_data_offset_ += new_offset;
+    DCHECK(data_in_buffer <= kBufferSize);
+
+    // Did we use all the data in the data chunk?
+    if (current_data_offset_ == current_data_length_) {
+      FlushCurrent();
+    }
+  }
+  return data_in_buffer;
+}
+
+
+bool ExternalStreamingStream::SetBookmark() {
+  // Bookmarking for this stream is a bit more complex than expected, since
+  // the stream state is distributed over several places:
+  // - pos_ (inherited from Utf16CharacterStream)
+  // - buffer_cursor_ and buffer_end_ (also from Utf16CharacterStream)
+  // - buffer_ (from BufferedUtf16CharacterStream)
+  // - current_data_ (+ .._offset_ and .._length) (this class)
+  // - utf8_split_char_buffer_* (a partial utf8 symbol at the block boundary)
+  //
+  // The underlying source_stream_ instance likely could re-construct this
+  // local data for us, but with the given interfaces we have no way of
+  // accomplishing this. Thus, we'll have to save all data locally.
+  //
+  // What gets saved where:
+  // - pos_  =>  bookmark_
+  // - buffer_[buffer_cursor_ .. buffer_end_]  =>  bookmark_buffer_
+  // - current_data_[.._offset_ .. .._length_]  =>  bookmark_data_
+  // - utf8_split_char_buffer_* => bookmark_utf8_split...
+  //
+  // To make sure we don't unnecessarily copy data, we also maintain
+  // whether bookmark_data_ contains a copy of the current current_data_
+  // block. This is done with:
+  // - bookmark_data_is_from_current_data_
+  // - bookmark_data_offset_: offset into bookmark_data_
+  //
+  // Note that bookmark_data_is_from_current_data_ must be maintained
+  // whenever current_data_ is updated.
+
+  bookmark_ = pos_;
+
+  size_t buffer_length = buffer_end_ - buffer_cursor_;
+  bookmark_buffer_.Dispose();
+  bookmark_buffer_ = Vector<uint16_t>::New(static_cast<int>(buffer_length));
+  CopyCharsUnsigned(bookmark_buffer_.start(), buffer_cursor_, buffer_length);
+
+  size_t data_length = current_data_length_ - current_data_offset_;
+  size_t bookmark_data_length = static_cast<size_t>(bookmark_data_.length());
+  if (bookmark_data_is_from_current_data_ &&
+      data_length < bookmark_data_length) {
+    // Fast case: bookmark_data_ was previously copied from the current
+    //            data block, and we have enough data for this bookmark.
+    bookmark_data_offset_ = bookmark_data_length - data_length;
+  } else {
+    // Slow case: We need to copy current_data_.
+    bookmark_data_.Dispose();
+    bookmark_data_ = Vector<uint8_t>::New(static_cast<int>(data_length));
+    CopyBytes(bookmark_data_.start(), current_data_ + current_data_offset_,
+              data_length);
+    bookmark_data_is_from_current_data_ = true;
+    bookmark_data_offset_ = 0;
+  }
+
+  bookmark_utf8_split_char_buffer_length_ = utf8_split_char_buffer_length_;
+  for (size_t i = 0; i < utf8_split_char_buffer_length_; i++) {
+    bookmark_utf8_split_char_buffer_[i] = utf8_split_char_buffer_[i];
+  }
+
+  return source_stream_->SetBookmark();
+}
+
+
+void ExternalStreamingStream::ResetToBookmark() {
+  source_stream_->ResetToBookmark();
+  FlushCurrent();
+
+  pos_ = bookmark_;
+
+  // bookmark_data_* => current_data_*
+  // (current_data_ assumes ownership of its memory.)
+  current_data_offset_ = 0;
+  current_data_length_ = bookmark_data_.length() - bookmark_data_offset_;
+  uint8_t* data = new uint8_t[current_data_length_];
+  CopyCharsUnsigned(data, bookmark_data_.begin() + bookmark_data_offset_,
+                    current_data_length_);
+  delete[] current_data_;
+  current_data_ = data;
+  bookmark_data_is_from_current_data_ = true;
+
+  // bookmark_buffer_ needs to be copied to buffer_.
+  CopyCharsUnsigned(buffer_, bookmark_buffer_.begin(),
+                    bookmark_buffer_.length());
+  buffer_cursor_ = buffer_;
+  buffer_end_ = buffer_ + bookmark_buffer_.length();
+
+  // utf8 split char buffer
+  utf8_split_char_buffer_length_ = bookmark_utf8_split_char_buffer_length_;
+  for (size_t i = 0; i < bookmark_utf8_split_char_buffer_length_; i++) {
+    utf8_split_char_buffer_[i] = bookmark_utf8_split_char_buffer_[i];
+  }
+}
+
+
+void ExternalStreamingStream::FlushCurrent() {
+  delete[] current_data_;
+  current_data_ = NULL;
+  current_data_length_ = 0;
+  current_data_offset_ = 0;
+  bookmark_data_is_from_current_data_ = false;
+}
+
+
+void ExternalStreamingStream::HandleUtf8SplitCharacters(
+    size_t* data_in_buffer) {
+  // Note the following property of UTF-8 which makes this function possible:
+  // Given any byte, we can always read its local environment (in both
+  // directions) to find out the (possibly multi-byte) character it belongs
+  // to. Single byte characters are of the form 0b0XXXXXXX. The first byte of a
+  // multi-byte character is of the form 0b110XXXXX, 0b1110XXXX or
+  // 0b11110XXX. The continuation bytes are of the form 0b10XXXXXX.
+
+  // First check if we have leftover data from the last chunk.
+  unibrow::uchar c;
+  if (utf8_split_char_buffer_length_ > 0) {
+    // Move the bytes which are part of the split character (which started in
+    // the previous chunk) into utf8_split_char_buffer_. Note that the
+    // continuation bytes are of the form 0b10XXXXXX, thus c >> 6 == 2.
+    while (current_data_offset_ < current_data_length_ &&
+           utf8_split_char_buffer_length_ < 4 &&
+           (c = current_data_[current_data_offset_]) >> 6 == 2) {
+      utf8_split_char_buffer_[utf8_split_char_buffer_length_] = c;
+      ++utf8_split_char_buffer_length_;
+      ++current_data_offset_;
+    }
+
+    // Convert the data in utf8_split_char_buffer_.
+    size_t new_offset = 0;
+    size_t new_chars_in_buffer =
+        CopyCharsHelper(buffer_ + *data_in_buffer,
+                        kBufferSize - *data_in_buffer, utf8_split_char_buffer_,
+                        &new_offset, utf8_split_char_buffer_length_, encoding_);
+    *data_in_buffer += new_chars_in_buffer;
+    // Make sure we used all the data.
+    DCHECK(new_offset == utf8_split_char_buffer_length_);
+    DCHECK(*data_in_buffer <= kBufferSize);
+
+    utf8_split_char_buffer_length_ = 0;
+  }
+
+  // Move bytes which are part of an incomplete character from the end of the
+  // current chunk to utf8_split_char_buffer_. They will be converted when the
+  // next data chunk arrives. Note that all valid UTF-8 characters are at most 4
+  // bytes long, but if the data is invalid, we can have character values bigger
+  // than unibrow::Utf8::kMaxOneByteChar for more than 4 consecutive bytes.
+  while (current_data_length_ > current_data_offset_ &&
+         (c = current_data_[current_data_length_ - 1]) >
+             unibrow::Utf8::kMaxOneByteChar &&
+         utf8_split_char_buffer_length_ < 4) {
+    --current_data_length_;
+    ++utf8_split_char_buffer_length_;
+    if (c >= (3 << 6)) {
+      // 3 << 6 = 0b11000000; this is the first byte of the multi-byte
+      // character. No need to copy the previous characters into the conversion
+      // buffer (even if they're multi-byte).
+      break;
+    }
+  }
+  CHECK(utf8_split_char_buffer_length_ <= 4);
+  for (size_t i = 0; i < utf8_split_char_buffer_length_; ++i) {
+    utf8_split_char_buffer_[i] = current_data_[current_data_length_ + i];
+  }
+}
+
+
+// ----------------------------------------------------------------------------
+// ExternalTwoByteStringUtf16CharacterStream
+
+ExternalTwoByteStringUtf16CharacterStream::
+    ~ExternalTwoByteStringUtf16CharacterStream() { }
+
+
+ExternalTwoByteStringUtf16CharacterStream::
+    ExternalTwoByteStringUtf16CharacterStream(
+        Handle<ExternalTwoByteString> data, int start_position,
+        int end_position)
+    : Utf16CharacterStream(),
+      source_(data),
+      raw_data_(data->GetTwoByteData(start_position)),
+      bookmark_(kNoBookmark) {
+  buffer_cursor_ = raw_data_,
+  buffer_end_ = raw_data_ + (end_position - start_position);
+  pos_ = start_position;
+}
+
+
+bool ExternalTwoByteStringUtf16CharacterStream::SetBookmark() {
+  bookmark_ = pos_;
+  return true;
+}
+
+
+void ExternalTwoByteStringUtf16CharacterStream::ResetToBookmark() {
+  DCHECK(bookmark_ != kNoBookmark);
+  pos_ = bookmark_;
+  buffer_cursor_ = raw_data_ + bookmark_;
+}
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/scanner-character-streams.h b/src/parsing/scanner-character-streams.h
new file mode 100644
index 0000000..603db93
--- /dev/null
+++ b/src/parsing/scanner-character-streams.h
@@ -0,0 +1,189 @@
+// Copyright 2011 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_SCANNER_CHARACTER_STREAMS_H_
+#define V8_PARSING_SCANNER_CHARACTER_STREAMS_H_
+
+#include "src/handles.h"
+#include "src/parsing/scanner.h"
+#include "src/vector.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class ExternalTwoByteString;
+
+// A buffered character stream based on a random access character
+// source (ReadBlock can be called with pos_ pointing to any position,
+// even positions before the current).
+class BufferedUtf16CharacterStream: public Utf16CharacterStream {
+ public:
+  BufferedUtf16CharacterStream();
+  ~BufferedUtf16CharacterStream() override;
+
+  void PushBack(uc32 character) override;
+
+ protected:
+  static const size_t kBufferSize = 512;
+  static const size_t kPushBackStepSize = 16;
+
+  size_t SlowSeekForward(size_t delta) override;
+  bool ReadBlock() override;
+  virtual void SlowPushBack(uc16 character);
+
+  virtual size_t BufferSeekForward(size_t delta) = 0;
+  virtual size_t FillBuffer(size_t position) = 0;
+
+  const uc16* pushback_limit_;
+  uc16 buffer_[kBufferSize];
+};
+
+
+// Generic string stream.
+class GenericStringUtf16CharacterStream: public BufferedUtf16CharacterStream {
+ public:
+  GenericStringUtf16CharacterStream(Handle<String> data, size_t start_position,
+                                    size_t end_position);
+  ~GenericStringUtf16CharacterStream() override;
+
+  bool SetBookmark() override;
+  void ResetToBookmark() override;
+
+ protected:
+  static const size_t kNoBookmark = -1;
+
+  size_t BufferSeekForward(size_t delta) override;
+  size_t FillBuffer(size_t position) override;
+
+  Handle<String> string_;
+  size_t length_;
+  size_t bookmark_;
+};
+
+
+// Utf16 stream based on a literal UTF-8 string.
+class Utf8ToUtf16CharacterStream: public BufferedUtf16CharacterStream {
+ public:
+  Utf8ToUtf16CharacterStream(const byte* data, size_t length);
+  ~Utf8ToUtf16CharacterStream() override;
+
+  static size_t CopyChars(uint16_t* dest, size_t length, const byte* src,
+                          size_t* src_pos, size_t src_length);
+
+ protected:
+  size_t BufferSeekForward(size_t delta) override;
+  size_t FillBuffer(size_t char_position) override;
+  void SetRawPosition(size_t char_position);
+
+  const byte* raw_data_;
+  size_t raw_data_length_;  // Measured in bytes, not characters.
+  size_t raw_data_pos_;
+  // The character position of the character at raw_data[raw_data_pos_].
+  // Not necessarily the same as pos_.
+  size_t raw_character_position_;
+};
+
+
+// ExternalStreamingStream is a wrapper around an ExternalSourceStream (see
+// include/v8.h) subclass implemented by the embedder.
+class ExternalStreamingStream : public BufferedUtf16CharacterStream {
+ public:
+  ExternalStreamingStream(ScriptCompiler::ExternalSourceStream* source_stream,
+                          v8::ScriptCompiler::StreamedSource::Encoding encoding)
+      : source_stream_(source_stream),
+        encoding_(encoding),
+        current_data_(NULL),
+        current_data_offset_(0),
+        current_data_length_(0),
+        utf8_split_char_buffer_length_(0),
+        bookmark_(0),
+        bookmark_data_is_from_current_data_(false),
+        bookmark_data_offset_(0),
+        bookmark_utf8_split_char_buffer_length_(0) {}
+
+  ~ExternalStreamingStream() override {
+    delete[] current_data_;
+    bookmark_buffer_.Dispose();
+    bookmark_data_.Dispose();
+  }
+
+  size_t BufferSeekForward(size_t delta) override {
+    // We never need to seek forward when streaming scripts. We only seek
+    // forward when we want to parse a function whose location we already know,
+    // and when streaming, we don't know the locations of anything we haven't
+    // seen yet.
+    UNREACHABLE();
+    return 0;
+  }
+
+  size_t FillBuffer(size_t position) override;
+
+  bool SetBookmark() override;
+  void ResetToBookmark() override;
+
+ private:
+  void HandleUtf8SplitCharacters(size_t* data_in_buffer);
+  void FlushCurrent();
+
+  ScriptCompiler::ExternalSourceStream* source_stream_;
+  v8::ScriptCompiler::StreamedSource::Encoding encoding_;
+  const uint8_t* current_data_;
+  size_t current_data_offset_;
+  size_t current_data_length_;
+  // For converting UTF-8 characters which are split across two data chunks.
+  uint8_t utf8_split_char_buffer_[4];
+  size_t utf8_split_char_buffer_length_;
+
+  // Bookmark support. See comments in ExternalStreamingStream::SetBookmark
+  // for additional details.
+  size_t bookmark_;
+  Vector<uint16_t> bookmark_buffer_;
+  Vector<uint8_t> bookmark_data_;
+  bool bookmark_data_is_from_current_data_;
+  size_t bookmark_data_offset_;
+  uint8_t bookmark_utf8_split_char_buffer_[4];
+  size_t bookmark_utf8_split_char_buffer_length_;
+};
+
+
+// UTF16 buffer to read characters from an external string.
+class ExternalTwoByteStringUtf16CharacterStream: public Utf16CharacterStream {
+ public:
+  ExternalTwoByteStringUtf16CharacterStream(Handle<ExternalTwoByteString> data,
+                                            int start_position,
+                                            int end_position);
+  ~ExternalTwoByteStringUtf16CharacterStream() override;
+
+  void PushBack(uc32 character) override {
+    DCHECK(buffer_cursor_ > raw_data_);
+    buffer_cursor_--;
+    pos_--;
+  }
+
+  bool SetBookmark() override;
+  void ResetToBookmark() override;
+
+ protected:
+  size_t SlowSeekForward(size_t delta) override {
+    // Fast case always handles seeking.
+    return 0;
+  }
+  bool ReadBlock() override {
+    // Entire string is read at start.
+    return false;
+  }
+  Handle<ExternalTwoByteString> source_;
+  const uc16* raw_data_;  // Pointer to the actual array of characters.
+
+ private:
+  static const size_t kNoBookmark = -1;
+
+  size_t bookmark_;
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_SCANNER_CHARACTER_STREAMS_H_
diff --git a/src/parsing/scanner.cc b/src/parsing/scanner.cc
new file mode 100644
index 0000000..7317593
--- /dev/null
+++ b/src/parsing/scanner.cc
@@ -0,0 +1,1673 @@
+// Copyright 2011 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.
+
+// Features shared by parsing and pre-parsing scanners.
+
+#include "src/parsing/scanner.h"
+
+#include <stdint.h>
+
+#include <cmath>
+
+#include "src/ast/ast-value-factory.h"
+#include "src/char-predicates-inl.h"
+#include "src/conversions-inl.h"
+#include "src/list-inl.h"
+#include "src/parsing/parser.h"
+
+namespace v8 {
+namespace internal {
+
+
+Handle<String> LiteralBuffer::Internalize(Isolate* isolate) const {
+  if (is_one_byte()) {
+    return isolate->factory()->InternalizeOneByteString(one_byte_literal());
+  }
+  return isolate->factory()->InternalizeTwoByteString(two_byte_literal());
+}
+
+
+// Default implementation for streams that do not support bookmarks.
+bool Utf16CharacterStream::SetBookmark() { return false; }
+void Utf16CharacterStream::ResetToBookmark() { UNREACHABLE(); }
+
+
+// ----------------------------------------------------------------------------
+// Scanner
+
+Scanner::Scanner(UnicodeCache* unicode_cache)
+    : unicode_cache_(unicode_cache),
+      bookmark_c0_(kNoBookmark),
+      octal_pos_(Location::invalid()) {
+  bookmark_current_.literal_chars = &bookmark_current_literal_;
+  bookmark_current_.raw_literal_chars = &bookmark_current_raw_literal_;
+  bookmark_next_.literal_chars = &bookmark_next_literal_;
+  bookmark_next_.raw_literal_chars = &bookmark_next_raw_literal_;
+}
+
+
+void Scanner::Initialize(Utf16CharacterStream* source) {
+  source_ = source;
+  // Need to capture identifiers in order to recognize "get" and "set"
+  // in object literals.
+  Init();
+  // Skip initial whitespace allowing HTML comment ends just like
+  // after a newline and scan first token.
+  has_line_terminator_before_next_ = true;
+  SkipWhiteSpace();
+  Scan();
+}
+
+
+template <bool capture_raw>
+uc32 Scanner::ScanHexNumber(int expected_length) {
+  DCHECK(expected_length <= 4);  // prevent overflow
+
+  uc32 x = 0;
+  for (int i = 0; i < expected_length; i++) {
+    int d = HexValue(c0_);
+    if (d < 0) {
+      return -1;
+    }
+    x = x * 16 + d;
+    Advance<capture_raw>();
+  }
+
+  return x;
+}
+
+
+template <bool capture_raw>
+uc32 Scanner::ScanUnlimitedLengthHexNumber(int max_value) {
+  uc32 x = 0;
+  int d = HexValue(c0_);
+  if (d < 0) {
+    return -1;
+  }
+  while (d >= 0) {
+    x = x * 16 + d;
+    if (x > max_value) return -1;
+    Advance<capture_raw>();
+    d = HexValue(c0_);
+  }
+  return x;
+}
+
+
+// Ensure that tokens can be stored in a byte.
+STATIC_ASSERT(Token::NUM_TOKENS <= 0x100);
+
+// Table of one-character tokens, by character (0x00..0x7f only).
+static const byte one_char_tokens[] = {
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::LPAREN,       // 0x28
+  Token::RPAREN,       // 0x29
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::COMMA,        // 0x2c
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::COLON,        // 0x3a
+  Token::SEMICOLON,    // 0x3b
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::CONDITIONAL,  // 0x3f
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::LBRACK,     // 0x5b
+  Token::ILLEGAL,
+  Token::RBRACK,     // 0x5d
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::LBRACE,       // 0x7b
+  Token::ILLEGAL,
+  Token::RBRACE,       // 0x7d
+  Token::BIT_NOT,      // 0x7e
+  Token::ILLEGAL
+};
+
+
+Token::Value Scanner::Next() {
+  if (next_.token == Token::EOS) {
+    next_.location.beg_pos = current_.location.beg_pos;
+    next_.location.end_pos = current_.location.end_pos;
+  }
+  current_ = next_;
+  if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) {
+    next_ = next_next_;
+    next_next_.token = Token::UNINITIALIZED;
+    return current_.token;
+  }
+  has_line_terminator_before_next_ = false;
+  has_multiline_comment_before_next_ = false;
+  if (static_cast<unsigned>(c0_) <= 0x7f) {
+    Token::Value token = static_cast<Token::Value>(one_char_tokens[c0_]);
+    if (token != Token::ILLEGAL) {
+      int pos = source_pos();
+      next_.token = token;
+      next_.location.beg_pos = pos;
+      next_.location.end_pos = pos + 1;
+      Advance();
+      return current_.token;
+    }
+  }
+  Scan();
+  return current_.token;
+}
+
+
+Token::Value Scanner::PeekAhead() {
+  if (next_next_.token != Token::UNINITIALIZED) {
+    return next_next_.token;
+  }
+  TokenDesc prev = current_;
+  Next();
+  Token::Value ret = next_.token;
+  next_next_ = next_;
+  next_ = current_;
+  current_ = prev;
+  return ret;
+}
+
+
+// TODO(yangguo): check whether this is actually necessary.
+static inline bool IsLittleEndianByteOrderMark(uc32 c) {
+  // The Unicode value U+FFFE is guaranteed never to be assigned as a
+  // Unicode character; this implies that in a Unicode context the
+  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
+  // character expressed in little-endian byte order (since it could
+  // not be a U+FFFE character expressed in big-endian byte
+  // order). Nevertheless, we check for it to be compatible with
+  // Spidermonkey.
+  return c == 0xFFFE;
+}
+
+
+bool Scanner::SkipWhiteSpace() {
+  int start_position = source_pos();
+
+  while (true) {
+    while (true) {
+      // The unicode cache accepts unsigned inputs.
+      if (c0_ < 0) break;
+      // Advance as long as character is a WhiteSpace or LineTerminator.
+      // Remember if the latter is the case.
+      if (unicode_cache_->IsLineTerminator(c0_)) {
+        has_line_terminator_before_next_ = true;
+      } else if (!unicode_cache_->IsWhiteSpace(c0_) &&
+                 !IsLittleEndianByteOrderMark(c0_)) {
+        break;
+      }
+      Advance();
+    }
+
+    // If there is an HTML comment end '-->' at the beginning of a
+    // line (with only whitespace in front of it), we treat the rest
+    // of the line as a comment. This is in line with the way
+    // SpiderMonkey handles it.
+    if (c0_ == '-' && has_line_terminator_before_next_) {
+      Advance();
+      if (c0_ == '-') {
+        Advance();
+        if (c0_ == '>') {
+          // Treat the rest of the line as a comment.
+          SkipSingleLineComment();
+          // Continue skipping white space after the comment.
+          continue;
+        }
+        PushBack('-');  // undo Advance()
+      }
+      PushBack('-');  // undo Advance()
+    }
+    // Return whether or not we skipped any characters.
+    return source_pos() != start_position;
+  }
+}
+
+
+Token::Value Scanner::SkipSingleLineComment() {
+  Advance();
+
+  // The line terminator at the end of the line is not considered
+  // to be part of the single-line comment; it is recognized
+  // separately by the lexical grammar and becomes part of the
+  // stream of input elements for the syntactic grammar (see
+  // ECMA-262, section 7.4).
+  while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
+    Advance();
+  }
+
+  return Token::WHITESPACE;
+}
+
+
+Token::Value Scanner::SkipSourceURLComment() {
+  TryToParseSourceURLComment();
+  while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
+    Advance();
+  }
+
+  return Token::WHITESPACE;
+}
+
+
+void Scanner::TryToParseSourceURLComment() {
+  // Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this
+  // function will just return if it cannot parse a magic comment.
+  if (c0_ < 0 || !unicode_cache_->IsWhiteSpace(c0_)) return;
+  Advance();
+  LiteralBuffer name;
+  while (c0_ >= 0 && !unicode_cache_->IsWhiteSpaceOrLineTerminator(c0_) &&
+         c0_ != '=') {
+    name.AddChar(c0_);
+    Advance();
+  }
+  if (!name.is_one_byte()) return;
+  Vector<const uint8_t> name_literal = name.one_byte_literal();
+  LiteralBuffer* value;
+  if (name_literal == STATIC_CHAR_VECTOR("sourceURL")) {
+    value = &source_url_;
+  } else if (name_literal == STATIC_CHAR_VECTOR("sourceMappingURL")) {
+    value = &source_mapping_url_;
+  } else {
+    return;
+  }
+  if (c0_ != '=')
+    return;
+  Advance();
+  value->Reset();
+  while (c0_ >= 0 && unicode_cache_->IsWhiteSpace(c0_)) {
+    Advance();
+  }
+  while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
+    // Disallowed characters.
+    if (c0_ == '"' || c0_ == '\'') {
+      value->Reset();
+      return;
+    }
+    if (unicode_cache_->IsWhiteSpace(c0_)) {
+      break;
+    }
+    value->AddChar(c0_);
+    Advance();
+  }
+  // Allow whitespace at the end.
+  while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
+    if (!unicode_cache_->IsWhiteSpace(c0_)) {
+      value->Reset();
+      break;
+    }
+    Advance();
+  }
+}
+
+
+Token::Value Scanner::SkipMultiLineComment() {
+  DCHECK(c0_ == '*');
+  Advance();
+
+  while (c0_ >= 0) {
+    uc32 ch = c0_;
+    Advance();
+    if (c0_ >= 0 && unicode_cache_->IsLineTerminator(ch)) {
+      // Following ECMA-262, section 7.4, a comment containing
+      // a newline will make the comment count as a line-terminator.
+      has_multiline_comment_before_next_ = true;
+    }
+    // If we have reached the end of the multi-line comment, we
+    // consume the '/' and insert a whitespace. This way all
+    // multi-line comments are treated as whitespace.
+    if (ch == '*' && c0_ == '/') {
+      c0_ = ' ';
+      return Token::WHITESPACE;
+    }
+  }
+
+  // Unterminated multi-line comment.
+  return Token::ILLEGAL;
+}
+
+
+Token::Value Scanner::ScanHtmlComment() {
+  // Check for <!-- comments.
+  DCHECK(c0_ == '!');
+  Advance();
+  if (c0_ == '-') {
+    Advance();
+    if (c0_ == '-') return SkipSingleLineComment();
+    PushBack('-');  // undo Advance()
+  }
+  PushBack('!');  // undo Advance()
+  DCHECK(c0_ == '!');
+  return Token::LT;
+}
+
+
+void Scanner::Scan() {
+  next_.literal_chars = NULL;
+  next_.raw_literal_chars = NULL;
+  Token::Value token;
+  do {
+    // Remember the position of the next token
+    next_.location.beg_pos = source_pos();
+
+    switch (c0_) {
+      case ' ':
+      case '\t':
+        Advance();
+        token = Token::WHITESPACE;
+        break;
+
+      case '\n':
+        Advance();
+        has_line_terminator_before_next_ = true;
+        token = Token::WHITESPACE;
+        break;
+
+      case '"': case '\'':
+        token = ScanString();
+        break;
+
+      case '<':
+        // < <= << <<= <!--
+        Advance();
+        if (c0_ == '=') {
+          token = Select(Token::LTE);
+        } else if (c0_ == '<') {
+          token = Select('=', Token::ASSIGN_SHL, Token::SHL);
+        } else if (c0_ == '!') {
+          token = ScanHtmlComment();
+        } else {
+          token = Token::LT;
+        }
+        break;
+
+      case '>':
+        // > >= >> >>= >>> >>>=
+        Advance();
+        if (c0_ == '=') {
+          token = Select(Token::GTE);
+        } else if (c0_ == '>') {
+          // >> >>= >>> >>>=
+          Advance();
+          if (c0_ == '=') {
+            token = Select(Token::ASSIGN_SAR);
+          } else if (c0_ == '>') {
+            token = Select('=', Token::ASSIGN_SHR, Token::SHR);
+          } else {
+            token = Token::SAR;
+          }
+        } else {
+          token = Token::GT;
+        }
+        break;
+
+      case '=':
+        // = == === =>
+        Advance();
+        if (c0_ == '=') {
+          token = Select('=', Token::EQ_STRICT, Token::EQ);
+        } else if (c0_ == '>') {
+          token = Select(Token::ARROW);
+        } else {
+          token = Token::ASSIGN;
+        }
+        break;
+
+      case '!':
+        // ! != !==
+        Advance();
+        if (c0_ == '=') {
+          token = Select('=', Token::NE_STRICT, Token::NE);
+        } else {
+          token = Token::NOT;
+        }
+        break;
+
+      case '+':
+        // + ++ +=
+        Advance();
+        if (c0_ == '+') {
+          token = Select(Token::INC);
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_ADD);
+        } else {
+          token = Token::ADD;
+        }
+        break;
+
+      case '-':
+        // - -- --> -=
+        Advance();
+        if (c0_ == '-') {
+          Advance();
+          if (c0_ == '>' && has_line_terminator_before_next_) {
+            // For compatibility with SpiderMonkey, we skip lines that
+            // start with an HTML comment end '-->'.
+            token = SkipSingleLineComment();
+          } else {
+            token = Token::DEC;
+          }
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_SUB);
+        } else {
+          token = Token::SUB;
+        }
+        break;
+
+      case '*':
+        // * *=
+        token = Select('=', Token::ASSIGN_MUL, Token::MUL);
+        break;
+
+      case '%':
+        // % %=
+        token = Select('=', Token::ASSIGN_MOD, Token::MOD);
+        break;
+
+      case '/':
+        // /  // /* /=
+        Advance();
+        if (c0_ == '/') {
+          Advance();
+          if (c0_ == '#' || c0_ == '@') {
+            Advance();
+            token = SkipSourceURLComment();
+          } else {
+            PushBack(c0_);
+            token = SkipSingleLineComment();
+          }
+        } else if (c0_ == '*') {
+          token = SkipMultiLineComment();
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_DIV);
+        } else {
+          token = Token::DIV;
+        }
+        break;
+
+      case '&':
+        // & && &=
+        Advance();
+        if (c0_ == '&') {
+          token = Select(Token::AND);
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_BIT_AND);
+        } else {
+          token = Token::BIT_AND;
+        }
+        break;
+
+      case '|':
+        // | || |=
+        Advance();
+        if (c0_ == '|') {
+          token = Select(Token::OR);
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_BIT_OR);
+        } else {
+          token = Token::BIT_OR;
+        }
+        break;
+
+      case '^':
+        // ^ ^=
+        token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
+        break;
+
+      case '.':
+        // . Number
+        Advance();
+        if (IsDecimalDigit(c0_)) {
+          token = ScanNumber(true);
+        } else {
+          token = Token::PERIOD;
+          if (c0_ == '.') {
+            Advance();
+            if (c0_ == '.') {
+              Advance();
+              token = Token::ELLIPSIS;
+            } else {
+              PushBack('.');
+            }
+          }
+        }
+        break;
+
+      case ':':
+        token = Select(Token::COLON);
+        break;
+
+      case ';':
+        token = Select(Token::SEMICOLON);
+        break;
+
+      case ',':
+        token = Select(Token::COMMA);
+        break;
+
+      case '(':
+        token = Select(Token::LPAREN);
+        break;
+
+      case ')':
+        token = Select(Token::RPAREN);
+        break;
+
+      case '[':
+        token = Select(Token::LBRACK);
+        break;
+
+      case ']':
+        token = Select(Token::RBRACK);
+        break;
+
+      case '{':
+        token = Select(Token::LBRACE);
+        break;
+
+      case '}':
+        token = Select(Token::RBRACE);
+        break;
+
+      case '?':
+        token = Select(Token::CONDITIONAL);
+        break;
+
+      case '~':
+        token = Select(Token::BIT_NOT);
+        break;
+
+      case '`':
+        token = ScanTemplateStart();
+        break;
+
+      default:
+        if (c0_ < 0) {
+          token = Token::EOS;
+        } else if (unicode_cache_->IsIdentifierStart(c0_)) {
+          token = ScanIdentifierOrKeyword();
+        } else if (IsDecimalDigit(c0_)) {
+          token = ScanNumber(false);
+        } else if (SkipWhiteSpace()) {
+          token = Token::WHITESPACE;
+        } else {
+          token = Select(Token::ILLEGAL);
+        }
+        break;
+    }
+
+    // Continue scanning for tokens as long as we're just skipping
+    // whitespace.
+  } while (token == Token::WHITESPACE);
+
+  next_.location.end_pos = source_pos();
+  next_.token = token;
+}
+
+
+void Scanner::SeekForward(int pos) {
+  // After this call, we will have the token at the given position as
+  // the "next" token. The "current" token will be invalid.
+  if (pos == next_.location.beg_pos) return;
+  int current_pos = source_pos();
+  DCHECK_EQ(next_.location.end_pos, current_pos);
+  // Positions inside the lookahead token aren't supported.
+  DCHECK(pos >= current_pos);
+  if (pos != current_pos) {
+    source_->SeekForward(pos - source_->pos());
+    Advance();
+    // This function is only called to seek to the location
+    // of the end of a function (at the "}" token). It doesn't matter
+    // whether there was a line terminator in the part we skip.
+    has_line_terminator_before_next_ = false;
+    has_multiline_comment_before_next_ = false;
+  }
+  Scan();
+}
+
+
+template <bool capture_raw, bool in_template_literal>
+bool Scanner::ScanEscape() {
+  uc32 c = c0_;
+  Advance<capture_raw>();
+
+  // Skip escaped newlines.
+  if (!in_template_literal && c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) {
+    // Allow CR+LF newlines in multiline string literals.
+    if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
+    // Allow LF+CR newlines in multiline string literals.
+    if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance<capture_raw>();
+    return true;
+  }
+
+  switch (c) {
+    case '\'':  // fall through
+    case '"' :  // fall through
+    case '\\': break;
+    case 'b' : c = '\b'; break;
+    case 'f' : c = '\f'; break;
+    case 'n' : c = '\n'; break;
+    case 'r' : c = '\r'; break;
+    case 't' : c = '\t'; break;
+    case 'u' : {
+      c = ScanUnicodeEscape<capture_raw>();
+      if (c < 0) return false;
+      break;
+    }
+    case 'v':
+      c = '\v';
+      break;
+    case 'x': {
+      c = ScanHexNumber<capture_raw>(2);
+      if (c < 0) return false;
+      break;
+    }
+    case '0':  // Fall through.
+    case '1':  // fall through
+    case '2':  // fall through
+    case '3':  // fall through
+    case '4':  // fall through
+    case '5':  // fall through
+    case '6':  // fall through
+    case '7':
+      c = ScanOctalEscape<capture_raw>(c, 2);
+      break;
+  }
+
+  // According to ECMA-262, section 7.8.4, characters not covered by the
+  // above cases should be illegal, but they are commonly handled as
+  // non-escaped characters by JS VMs.
+  AddLiteralChar(c);
+  return true;
+}
+
+
+// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
+// ECMA-262. Other JS VMs support them.
+template <bool capture_raw>
+uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
+  uc32 x = c - '0';
+  int i = 0;
+  for (; i < length; i++) {
+    int d = c0_ - '0';
+    if (d < 0 || d > 7) break;
+    int nx = x * 8 + d;
+    if (nx >= 256) break;
+    x = nx;
+    Advance<capture_raw>();
+  }
+  // Anything except '\0' is an octal escape sequence, illegal in strict mode.
+  // Remember the position of octal escape sequences so that an error
+  // can be reported later (in strict mode).
+  // We don't report the error immediately, because the octal escape can
+  // occur before the "use strict" directive.
+  if (c != '0' || i > 0) {
+    octal_pos_ = Location(source_pos() - i - 1, source_pos() - 1);
+  }
+  return x;
+}
+
+
+const int kMaxAscii = 127;
+
+
+Token::Value Scanner::ScanString() {
+  uc32 quote = c0_;
+  Advance<false, false>();  // consume quote
+
+  LiteralScope literal(this);
+  while (true) {
+    if (c0_ > kMaxAscii) {
+      HandleLeadSurrogate();
+      break;
+    }
+    if (c0_ < 0 || c0_ == '\n' || c0_ == '\r') return Token::ILLEGAL;
+    if (c0_ == quote) {
+      literal.Complete();
+      Advance<false, false>();
+      return Token::STRING;
+    }
+    uc32 c = c0_;
+    if (c == '\\') break;
+    Advance<false, false>();
+    AddLiteralChar(c);
+  }
+
+  while (c0_ != quote && c0_ >= 0
+         && !unicode_cache_->IsLineTerminator(c0_)) {
+    uc32 c = c0_;
+    Advance();
+    if (c == '\\') {
+      if (c0_ < 0 || !ScanEscape<false, false>()) return Token::ILLEGAL;
+    } else {
+      AddLiteralChar(c);
+    }
+  }
+  if (c0_ != quote) return Token::ILLEGAL;
+  literal.Complete();
+
+  Advance();  // consume quote
+  return Token::STRING;
+}
+
+
+Token::Value Scanner::ScanTemplateSpan() {
+  // When scanning a TemplateSpan, we are looking for the following construct:
+  // TEMPLATE_SPAN ::
+  //     ` LiteralChars* ${
+  //   | } LiteralChars* ${
+  //
+  // TEMPLATE_TAIL ::
+  //     ` LiteralChars* `
+  //   | } LiteralChar* `
+  //
+  // A TEMPLATE_SPAN should always be followed by an Expression, while a
+  // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
+  // followed by an Expression.
+
+  Token::Value result = Token::TEMPLATE_SPAN;
+  LiteralScope literal(this);
+  StartRawLiteral();
+  const bool capture_raw = true;
+  const bool in_template_literal = true;
+
+  while (true) {
+    uc32 c = c0_;
+    Advance<capture_raw>();
+    if (c == '`') {
+      result = Token::TEMPLATE_TAIL;
+      ReduceRawLiteralLength(1);
+      break;
+    } else if (c == '$' && c0_ == '{') {
+      Advance<capture_raw>();  // Consume '{'
+      ReduceRawLiteralLength(2);
+      break;
+    } else if (c == '\\') {
+      if (c0_ > 0 && unicode_cache_->IsLineTerminator(c0_)) {
+        // The TV of LineContinuation :: \ LineTerminatorSequence is the empty
+        // code unit sequence.
+        uc32 lastChar = c0_;
+        Advance<capture_raw>();
+        if (lastChar == '\r') {
+          ReduceRawLiteralLength(1);  // Remove \r
+          if (c0_ == '\n') {
+            Advance<capture_raw>();  // Adds \n
+          } else {
+            AddRawLiteralChar('\n');
+          }
+        }
+      } else if (!ScanEscape<capture_raw, in_template_literal>()) {
+        return Token::ILLEGAL;
+      }
+    } else if (c < 0) {
+      // Unterminated template literal
+      PushBack(c);
+      break;
+    } else {
+      // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
+      // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
+      // consisting of the CV 0x000A.
+      if (c == '\r') {
+        ReduceRawLiteralLength(1);  // Remove \r
+        if (c0_ == '\n') {
+          Advance<capture_raw>();  // Adds \n
+        } else {
+          AddRawLiteralChar('\n');
+        }
+        c = '\n';
+      }
+      AddLiteralChar(c);
+    }
+  }
+  literal.Complete();
+  next_.location.end_pos = source_pos();
+  next_.token = result;
+  return result;
+}
+
+
+Token::Value Scanner::ScanTemplateStart() {
+  DCHECK(c0_ == '`');
+  next_.location.beg_pos = source_pos();
+  Advance();  // Consume `
+  return ScanTemplateSpan();
+}
+
+
+Token::Value Scanner::ScanTemplateContinuation() {
+  DCHECK_EQ(next_.token, Token::RBRACE);
+  next_.location.beg_pos = source_pos() - 1;  // We already consumed }
+  return ScanTemplateSpan();
+}
+
+
+void Scanner::ScanDecimalDigits() {
+  while (IsDecimalDigit(c0_))
+    AddLiteralCharAdvance();
+}
+
+
+Token::Value Scanner::ScanNumber(bool seen_period) {
+  DCHECK(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
+
+  enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
+
+  LiteralScope literal(this);
+  bool at_start = !seen_period;
+  if (seen_period) {
+    // we have already seen a decimal point of the float
+    AddLiteralChar('.');
+    ScanDecimalDigits();  // we know we have at least one digit
+
+  } else {
+    // if the first character is '0' we must check for octals and hex
+    if (c0_ == '0') {
+      int start_pos = source_pos();  // For reporting octal positions.
+      AddLiteralCharAdvance();
+
+      // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
+      // an octal number.
+      if (c0_ == 'x' || c0_ == 'X') {
+        // hex number
+        kind = HEX;
+        AddLiteralCharAdvance();
+        if (!IsHexDigit(c0_)) {
+          // we must have at least one hex digit after 'x'/'X'
+          return Token::ILLEGAL;
+        }
+        while (IsHexDigit(c0_)) {
+          AddLiteralCharAdvance();
+        }
+      } else if (c0_ == 'o' || c0_ == 'O') {
+        kind = OCTAL;
+        AddLiteralCharAdvance();
+        if (!IsOctalDigit(c0_)) {
+          // we must have at least one octal digit after 'o'/'O'
+          return Token::ILLEGAL;
+        }
+        while (IsOctalDigit(c0_)) {
+          AddLiteralCharAdvance();
+        }
+      } else if (c0_ == 'b' || c0_ == 'B') {
+        kind = BINARY;
+        AddLiteralCharAdvance();
+        if (!IsBinaryDigit(c0_)) {
+          // we must have at least one binary digit after 'b'/'B'
+          return Token::ILLEGAL;
+        }
+        while (IsBinaryDigit(c0_)) {
+          AddLiteralCharAdvance();
+        }
+      } else if ('0' <= c0_ && c0_ <= '7') {
+        // (possible) octal number
+        kind = IMPLICIT_OCTAL;
+        while (true) {
+          if (c0_ == '8' || c0_ == '9') {
+            at_start = false;
+            kind = DECIMAL;
+            break;
+          }
+          if (c0_  < '0' || '7'  < c0_) {
+            // Octal literal finished.
+            octal_pos_ = Location(start_pos, source_pos());
+            break;
+          }
+          AddLiteralCharAdvance();
+        }
+      }
+    }
+
+    // Parse decimal digits and allow trailing fractional part.
+    if (kind == DECIMAL) {
+      if (at_start) {
+        uint64_t value = 0;
+        while (IsDecimalDigit(c0_)) {
+          value = 10 * value + (c0_ - '0');
+
+          uc32 first_char = c0_;
+          Advance<false, false>();
+          AddLiteralChar(first_char);
+        }
+
+        if (next_.literal_chars->one_byte_literal().length() <= 10 &&
+            value <= Smi::kMaxValue && c0_ != '.' && c0_ != 'e' && c0_ != 'E') {
+          next_.smi_value_ = static_cast<int>(value);
+          literal.Complete();
+          HandleLeadSurrogate();
+
+          return Token::SMI;
+        }
+        HandleLeadSurrogate();
+      }
+
+      ScanDecimalDigits();  // optional
+      if (c0_ == '.') {
+        AddLiteralCharAdvance();
+        ScanDecimalDigits();  // optional
+      }
+    }
+  }
+
+  // scan exponent, if any
+  if (c0_ == 'e' || c0_ == 'E') {
+    DCHECK(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
+    if (kind != DECIMAL) return Token::ILLEGAL;
+    // scan exponent
+    AddLiteralCharAdvance();
+    if (c0_ == '+' || c0_ == '-')
+      AddLiteralCharAdvance();
+    if (!IsDecimalDigit(c0_)) {
+      // we must have at least one decimal digit after 'e'/'E'
+      return Token::ILLEGAL;
+    }
+    ScanDecimalDigits();
+  }
+
+  // The source character immediately following a numeric literal must
+  // not be an identifier start or a decimal digit; see ECMA-262
+  // section 7.8.3, page 17 (note that we read only one decimal digit
+  // if the value is 0).
+  if (IsDecimalDigit(c0_) ||
+      (c0_ >= 0 && unicode_cache_->IsIdentifierStart(c0_)))
+    return Token::ILLEGAL;
+
+  literal.Complete();
+
+  return Token::NUMBER;
+}
+
+
+uc32 Scanner::ScanIdentifierUnicodeEscape() {
+  Advance();
+  if (c0_ != 'u') return -1;
+  Advance();
+  return ScanUnicodeEscape<false>();
+}
+
+
+template <bool capture_raw>
+uc32 Scanner::ScanUnicodeEscape() {
+  // Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
+  // hex digits between { } is arbitrary. \ and u have already been read.
+  if (c0_ == '{') {
+    Advance<capture_raw>();
+    uc32 cp = ScanUnlimitedLengthHexNumber<capture_raw>(0x10ffff);
+    if (cp < 0) {
+      return -1;
+    }
+    if (c0_ != '}') {
+      return -1;
+    }
+    Advance<capture_raw>();
+    return cp;
+  }
+  return ScanHexNumber<capture_raw>(4);
+}
+
+
+// ----------------------------------------------------------------------------
+// Keyword Matcher
+
+#define KEYWORDS(KEYWORD_GROUP, KEYWORD)                    \
+  KEYWORD_GROUP('b')                                        \
+  KEYWORD("break", Token::BREAK)                            \
+  KEYWORD_GROUP('c')                                        \
+  KEYWORD("case", Token::CASE)                              \
+  KEYWORD("catch", Token::CATCH)                            \
+  KEYWORD("class", Token::CLASS)                            \
+  KEYWORD("const", Token::CONST)                            \
+  KEYWORD("continue", Token::CONTINUE)                      \
+  KEYWORD_GROUP('d')                                        \
+  KEYWORD("debugger", Token::DEBUGGER)                      \
+  KEYWORD("default", Token::DEFAULT)                        \
+  KEYWORD("delete", Token::DELETE)                          \
+  KEYWORD("do", Token::DO)                                  \
+  KEYWORD_GROUP('e')                                        \
+  KEYWORD("else", Token::ELSE)                              \
+  KEYWORD("enum", Token::FUTURE_RESERVED_WORD)              \
+  KEYWORD("export", Token::EXPORT)                          \
+  KEYWORD("extends", Token::EXTENDS)                        \
+  KEYWORD_GROUP('f')                                        \
+  KEYWORD("false", Token::FALSE_LITERAL)                    \
+  KEYWORD("finally", Token::FINALLY)                        \
+  KEYWORD("for", Token::FOR)                                \
+  KEYWORD("function", Token::FUNCTION)                      \
+  KEYWORD_GROUP('i')                                        \
+  KEYWORD("if", Token::IF)                                  \
+  KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
+  KEYWORD("import", Token::IMPORT)                          \
+  KEYWORD("in", Token::IN)                                  \
+  KEYWORD("instanceof", Token::INSTANCEOF)                  \
+  KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD)  \
+  KEYWORD_GROUP('l')                                        \
+  KEYWORD("let", Token::LET)                                \
+  KEYWORD_GROUP('n')                                        \
+  KEYWORD("new", Token::NEW)                                \
+  KEYWORD("null", Token::NULL_LITERAL)                      \
+  KEYWORD_GROUP('p')                                        \
+  KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD)    \
+  KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD)    \
+  KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD)  \
+  KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD)     \
+  KEYWORD_GROUP('r')                                        \
+  KEYWORD("return", Token::RETURN)                          \
+  KEYWORD_GROUP('s')                                        \
+  KEYWORD("static", Token::STATIC)                          \
+  KEYWORD("super", Token::SUPER)                            \
+  KEYWORD("switch", Token::SWITCH)                          \
+  KEYWORD_GROUP('t')                                        \
+  KEYWORD("this", Token::THIS)                              \
+  KEYWORD("throw", Token::THROW)                            \
+  KEYWORD("true", Token::TRUE_LITERAL)                      \
+  KEYWORD("try", Token::TRY)                                \
+  KEYWORD("typeof", Token::TYPEOF)                          \
+  KEYWORD_GROUP('v')                                        \
+  KEYWORD("var", Token::VAR)                                \
+  KEYWORD("void", Token::VOID)                              \
+  KEYWORD_GROUP('w')                                        \
+  KEYWORD("while", Token::WHILE)                            \
+  KEYWORD("with", Token::WITH)                              \
+  KEYWORD_GROUP('y')                                        \
+  KEYWORD("yield", Token::YIELD)
+
+
+static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
+                                             int input_length, bool escaped) {
+  DCHECK(input_length >= 1);
+  const int kMinLength = 2;
+  const int kMaxLength = 10;
+  if (input_length < kMinLength || input_length > kMaxLength) {
+    return Token::IDENTIFIER;
+  }
+  switch (input[0]) {
+    default:
+#define KEYWORD_GROUP_CASE(ch)                                \
+      break;                                                  \
+    case ch:
+#define KEYWORD(keyword, token)                                     \
+  {                                                                 \
+    /* 'keyword' is a char array, so sizeof(keyword) is */          \
+    /* strlen(keyword) plus 1 for the NUL char. */                  \
+    const int keyword_length = sizeof(keyword) - 1;                 \
+    STATIC_ASSERT(keyword_length >= kMinLength);                    \
+    STATIC_ASSERT(keyword_length <= kMaxLength);                    \
+    if (input_length == keyword_length && input[1] == keyword[1] && \
+        (keyword_length <= 2 || input[2] == keyword[2]) &&          \
+        (keyword_length <= 3 || input[3] == keyword[3]) &&          \
+        (keyword_length <= 4 || input[4] == keyword[4]) &&          \
+        (keyword_length <= 5 || input[5] == keyword[5]) &&          \
+        (keyword_length <= 6 || input[6] == keyword[6]) &&          \
+        (keyword_length <= 7 || input[7] == keyword[7]) &&          \
+        (keyword_length <= 8 || input[8] == keyword[8]) &&          \
+        (keyword_length <= 9 || input[9] == keyword[9])) {          \
+      if (escaped) {                                                \
+        return token == Token::FUTURE_STRICT_RESERVED_WORD          \
+                   ? Token::ESCAPED_STRICT_RESERVED_WORD            \
+                   : Token::ESCAPED_KEYWORD;                        \
+      }                                                             \
+      return token;                                                 \
+    }                                                               \
+  }
+    KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
+  }
+  return Token::IDENTIFIER;
+}
+
+
+bool Scanner::IdentifierIsFutureStrictReserved(
+    const AstRawString* string) const {
+  // Keywords are always 1-byte strings.
+  if (!string->is_one_byte()) return false;
+  if (string->IsOneByteEqualTo("let") || string->IsOneByteEqualTo("static") ||
+      string->IsOneByteEqualTo("yield")) {
+    return true;
+  }
+  return Token::FUTURE_STRICT_RESERVED_WORD ==
+         KeywordOrIdentifierToken(string->raw_data(), string->length(), false);
+}
+
+
+Token::Value Scanner::ScanIdentifierOrKeyword() {
+  DCHECK(unicode_cache_->IsIdentifierStart(c0_));
+  LiteralScope literal(this);
+  if (IsInRange(c0_, 'a', 'z')) {
+    do {
+      uc32 first_char = c0_;
+      Advance<false, false>();
+      AddLiteralChar(first_char);
+    } while (IsInRange(c0_, 'a', 'z'));
+
+    if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '_' ||
+        c0_ == '$') {
+      // Identifier starting with lowercase.
+      uc32 first_char = c0_;
+      Advance<false, false>();
+      AddLiteralChar(first_char);
+      while (IsAsciiIdentifier(c0_)) {
+        uc32 first_char = c0_;
+        Advance<false, false>();
+        AddLiteralChar(first_char);
+      }
+      if (c0_ <= kMaxAscii && c0_ != '\\') {
+        literal.Complete();
+        return Token::IDENTIFIER;
+      }
+    } else if (c0_ <= kMaxAscii && c0_ != '\\') {
+      // Only a-z+: could be a keyword or identifier.
+      literal.Complete();
+      Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
+      return KeywordOrIdentifierToken(chars.start(), chars.length(), false);
+    }
+
+    HandleLeadSurrogate();
+  } else if (IsInRange(c0_, 'A', 'Z') || c0_ == '_' || c0_ == '$') {
+    do {
+      uc32 first_char = c0_;
+      Advance<false, false>();
+      AddLiteralChar(first_char);
+    } while (IsAsciiIdentifier(c0_));
+
+    if (c0_ <= kMaxAscii && c0_ != '\\') {
+      literal.Complete();
+      return Token::IDENTIFIER;
+    }
+
+    HandleLeadSurrogate();
+  } else if (c0_ == '\\') {
+    // Scan identifier start character.
+    uc32 c = ScanIdentifierUnicodeEscape();
+    // Only allow legal identifier start characters.
+    if (c < 0 ||
+        c == '\\' ||  // No recursive escapes.
+        !unicode_cache_->IsIdentifierStart(c)) {
+      return Token::ILLEGAL;
+    }
+    AddLiteralChar(c);
+    return ScanIdentifierSuffix(&literal, true);
+  } else {
+    uc32 first_char = c0_;
+    Advance();
+    AddLiteralChar(first_char);
+  }
+
+  // Scan the rest of the identifier characters.
+  while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
+    if (c0_ != '\\') {
+      uc32 next_char = c0_;
+      Advance();
+      AddLiteralChar(next_char);
+      continue;
+    }
+    // Fallthrough if no longer able to complete keyword.
+    return ScanIdentifierSuffix(&literal, false);
+  }
+
+  literal.Complete();
+
+  if (next_.literal_chars->is_one_byte()) {
+    Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
+    return KeywordOrIdentifierToken(chars.start(), chars.length(), false);
+  }
+  return Token::IDENTIFIER;
+}
+
+
+Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal,
+                                           bool escaped) {
+  // Scan the rest of the identifier characters.
+  while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
+    if (c0_ == '\\') {
+      uc32 c = ScanIdentifierUnicodeEscape();
+      escaped = true;
+      // Only allow legal identifier part characters.
+      if (c < 0 ||
+          c == '\\' ||
+          !unicode_cache_->IsIdentifierPart(c)) {
+        return Token::ILLEGAL;
+      }
+      AddLiteralChar(c);
+    } else {
+      AddLiteralChar(c0_);
+      Advance();
+    }
+  }
+  literal->Complete();
+
+  if (escaped && next_.literal_chars->is_one_byte()) {
+    Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
+    return KeywordOrIdentifierToken(chars.start(), chars.length(), true);
+  }
+  return Token::IDENTIFIER;
+}
+
+
+bool Scanner::ScanRegExpPattern(bool seen_equal) {
+  // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
+  bool in_character_class = false;
+
+  // Previous token is either '/' or '/=', in the second case, the
+  // pattern starts at =.
+  next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
+  next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
+
+  // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
+  // the scanner should pass uninterpreted bodies to the RegExp
+  // constructor.
+  LiteralScope literal(this);
+  if (seen_equal) {
+    AddLiteralChar('=');
+  }
+
+  while (c0_ != '/' || in_character_class) {
+    if (c0_ < 0 || unicode_cache_->IsLineTerminator(c0_)) return false;
+    if (c0_ == '\\') {  // Escape sequence.
+      AddLiteralCharAdvance();
+      if (c0_ < 0 || unicode_cache_->IsLineTerminator(c0_)) return false;
+      AddLiteralCharAdvance();
+      // If the escape allows more characters, i.e., \x??, \u????, or \c?,
+      // only "safe" characters are allowed (letters, digits, underscore),
+      // otherwise the escape isn't valid and the invalid character has
+      // its normal meaning. I.e., we can just continue scanning without
+      // worrying whether the following characters are part of the escape
+      // or not, since any '/', '\\' or '[' is guaranteed to not be part
+      // of the escape sequence.
+
+      // TODO(896): At some point, parse RegExps more throughly to capture
+      // octal esacpes in strict mode.
+    } else {  // Unescaped character.
+      if (c0_ == '[') in_character_class = true;
+      if (c0_ == ']') in_character_class = false;
+      AddLiteralCharAdvance();
+    }
+  }
+  Advance();  // consume '/'
+
+  literal.Complete();
+
+  return true;
+}
+
+
+Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() {
+  // Scan regular expression flags.
+  LiteralScope literal(this);
+  int flags = 0;
+  while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
+    RegExp::Flags flag = RegExp::kNone;
+    switch (c0_) {
+      case 'g':
+        flag = RegExp::kGlobal;
+        break;
+      case 'i':
+        flag = RegExp::kIgnoreCase;
+        break;
+      case 'm':
+        flag = RegExp::kMultiline;
+        break;
+      case 'u':
+        if (!FLAG_harmony_unicode_regexps) return Nothing<RegExp::Flags>();
+        flag = RegExp::kUnicode;
+        break;
+      case 'y':
+        if (!FLAG_harmony_regexps) return Nothing<RegExp::Flags>();
+        flag = RegExp::kSticky;
+        break;
+      default:
+        return Nothing<RegExp::Flags>();
+    }
+    if (flags & flag) return Nothing<RegExp::Flags>();
+    AddLiteralCharAdvance();
+    flags |= flag;
+  }
+  literal.Complete();
+
+  next_.location.end_pos = source_pos();
+  return Just(RegExp::Flags(flags));
+}
+
+
+const AstRawString* Scanner::CurrentSymbol(AstValueFactory* ast_value_factory) {
+  if (is_literal_one_byte()) {
+    return ast_value_factory->GetOneByteString(literal_one_byte_string());
+  }
+  return ast_value_factory->GetTwoByteString(literal_two_byte_string());
+}
+
+
+const AstRawString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) {
+  if (is_next_literal_one_byte()) {
+    return ast_value_factory->GetOneByteString(next_literal_one_byte_string());
+  }
+  return ast_value_factory->GetTwoByteString(next_literal_two_byte_string());
+}
+
+
+const AstRawString* Scanner::CurrentRawSymbol(
+    AstValueFactory* ast_value_factory) {
+  if (is_raw_literal_one_byte()) {
+    return ast_value_factory->GetOneByteString(raw_literal_one_byte_string());
+  }
+  return ast_value_factory->GetTwoByteString(raw_literal_two_byte_string());
+}
+
+
+double Scanner::DoubleValue() {
+  DCHECK(is_literal_one_byte());
+  return StringToDouble(
+      unicode_cache_,
+      literal_one_byte_string(),
+      ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
+}
+
+
+bool Scanner::ContainsDot() {
+  DCHECK(is_literal_one_byte());
+  Vector<const uint8_t> str = literal_one_byte_string();
+  return std::find(str.begin(), str.end(), '.') != str.end();
+}
+
+
+int Scanner::FindSymbol(DuplicateFinder* finder, int value) {
+  if (is_literal_one_byte()) {
+    return finder->AddOneByteSymbol(literal_one_byte_string(), value);
+  }
+  return finder->AddTwoByteSymbol(literal_two_byte_string(), value);
+}
+
+
+bool Scanner::SetBookmark() {
+  if (c0_ != kNoBookmark && bookmark_c0_ == kNoBookmark &&
+      next_next_.token == Token::UNINITIALIZED && source_->SetBookmark()) {
+    bookmark_c0_ = c0_;
+    CopyTokenDesc(&bookmark_current_, &current_);
+    CopyTokenDesc(&bookmark_next_, &next_);
+    return true;
+  }
+  return false;
+}
+
+
+void Scanner::ResetToBookmark() {
+  DCHECK(BookmarkHasBeenSet());  // Caller hasn't called SetBookmark.
+
+  source_->ResetToBookmark();
+  c0_ = bookmark_c0_;
+  StartLiteral();
+  StartRawLiteral();
+  CopyTokenDesc(&next_, &bookmark_current_);
+  current_ = next_;
+  StartLiteral();
+  StartRawLiteral();
+  CopyTokenDesc(&next_, &bookmark_next_);
+
+  bookmark_c0_ = kBookmarkWasApplied;
+}
+
+
+bool Scanner::BookmarkHasBeenSet() { return bookmark_c0_ >= 0; }
+
+
+bool Scanner::BookmarkHasBeenReset() {
+  return bookmark_c0_ == kBookmarkWasApplied;
+}
+
+
+void Scanner::DropBookmark() { bookmark_c0_ = kNoBookmark; }
+
+
+void Scanner::CopyTokenDesc(TokenDesc* to, TokenDesc* from) {
+  DCHECK_NOT_NULL(to);
+  DCHECK_NOT_NULL(from);
+  to->token = from->token;
+  to->location = from->location;
+  to->literal_chars->CopyFrom(from->literal_chars);
+  to->raw_literal_chars->CopyFrom(from->raw_literal_chars);
+}
+
+
+int DuplicateFinder::AddOneByteSymbol(Vector<const uint8_t> key, int value) {
+  return AddSymbol(key, true, value);
+}
+
+
+int DuplicateFinder::AddTwoByteSymbol(Vector<const uint16_t> key, int value) {
+  return AddSymbol(Vector<const uint8_t>::cast(key), false, value);
+}
+
+
+int DuplicateFinder::AddSymbol(Vector<const uint8_t> key,
+                               bool is_one_byte,
+                               int value) {
+  uint32_t hash = Hash(key, is_one_byte);
+  byte* encoding = BackupKey(key, is_one_byte);
+  HashMap::Entry* entry = map_.LookupOrInsert(encoding, hash);
+  int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
+  entry->value =
+    reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
+  return old_value;
+}
+
+
+int DuplicateFinder::AddNumber(Vector<const uint8_t> key, int value) {
+  DCHECK(key.length() > 0);
+  // Quick check for already being in canonical form.
+  if (IsNumberCanonical(key)) {
+    return AddOneByteSymbol(key, value);
+  }
+
+  int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY;
+  double double_value = StringToDouble(
+      unicode_constants_, key, flags, 0.0);
+  int length;
+  const char* string;
+  if (!std::isfinite(double_value)) {
+    string = "Infinity";
+    length = 8;  // strlen("Infinity");
+  } else {
+    string = DoubleToCString(double_value,
+                             Vector<char>(number_buffer_, kBufferSize));
+    length = StrLength(string);
+  }
+  return AddSymbol(Vector<const byte>(reinterpret_cast<const byte*>(string),
+                                      length), true, value);
+}
+
+
+bool DuplicateFinder::IsNumberCanonical(Vector<const uint8_t> number) {
+  // Test for a safe approximation of number literals that are already
+  // in canonical form: max 15 digits, no leading zeroes, except an
+  // integer part that is a single zero, and no trailing zeros below
+  // the decimal point.
+  int pos = 0;
+  int length = number.length();
+  if (number.length() > 15) return false;
+  if (number[pos] == '0') {
+    pos++;
+  } else {
+    while (pos < length &&
+           static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
+  }
+  if (length == pos) return true;
+  if (number[pos] != '.') return false;
+  pos++;
+  bool invalid_last_digit = true;
+  while (pos < length) {
+    uint8_t digit = number[pos] - '0';
+    if (digit > '9' - '0') return false;
+    invalid_last_digit = (digit == 0);
+    pos++;
+  }
+  return !invalid_last_digit;
+}
+
+
+uint32_t DuplicateFinder::Hash(Vector<const uint8_t> key, bool is_one_byte) {
+  // Primitive hash function, almost identical to the one used
+  // for strings (except that it's seeded by the length and representation).
+  int length = key.length();
+  uint32_t hash = (length << 1) | (is_one_byte ? 1 : 0);
+  for (int i = 0; i < length; i++) {
+    uint32_t c = key[i];
+    hash = (hash + c) * 1025;
+    hash ^= (hash >> 6);
+  }
+  return hash;
+}
+
+
+bool DuplicateFinder::Match(void* first, void* second) {
+  // Decode lengths.
+  // Length + representation is encoded as base 128, most significant heptet
+  // first, with a 8th bit being non-zero while there are more heptets.
+  // The value encodes the number of bytes following, and whether the original
+  // was Latin1.
+  byte* s1 = reinterpret_cast<byte*>(first);
+  byte* s2 = reinterpret_cast<byte*>(second);
+  uint32_t length_one_byte_field = 0;
+  byte c1;
+  do {
+    c1 = *s1;
+    if (c1 != *s2) return false;
+    length_one_byte_field = (length_one_byte_field << 7) | (c1 & 0x7f);
+    s1++;
+    s2++;
+  } while ((c1 & 0x80) != 0);
+  int length = static_cast<int>(length_one_byte_field >> 1);
+  return memcmp(s1, s2, length) == 0;
+}
+
+
+byte* DuplicateFinder::BackupKey(Vector<const uint8_t> bytes,
+                                 bool is_one_byte) {
+  uint32_t one_byte_length = (bytes.length() << 1) | (is_one_byte ? 1 : 0);
+  backing_store_.StartSequence();
+  // Emit one_byte_length as base-128 encoded number, with the 7th bit set
+  // on the byte of every heptet except the last, least significant, one.
+  if (one_byte_length >= (1 << 7)) {
+    if (one_byte_length >= (1 << 14)) {
+      if (one_byte_length >= (1 << 21)) {
+        if (one_byte_length >= (1 << 28)) {
+          backing_store_.Add(
+              static_cast<uint8_t>((one_byte_length >> 28) | 0x80));
+        }
+        backing_store_.Add(
+            static_cast<uint8_t>((one_byte_length >> 21) | 0x80u));
+      }
+      backing_store_.Add(
+          static_cast<uint8_t>((one_byte_length >> 14) | 0x80u));
+    }
+    backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u));
+  }
+  backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f));
+
+  backing_store_.AddBlock(bytes);
+  return backing_store_.EndSequence().start();
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/scanner.h b/src/parsing/scanner.h
new file mode 100644
index 0000000..1d0aba0
--- /dev/null
+++ b/src/parsing/scanner.h
@@ -0,0 +1,760 @@
+// Copyright 2011 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.
+
+// Features shared by parsing and pre-parsing scanners.
+
+#ifndef V8_PARSING_SCANNER_H_
+#define V8_PARSING_SCANNER_H_
+
+#include "src/allocation.h"
+#include "src/base/logging.h"
+#include "src/char-predicates.h"
+#include "src/globals.h"
+#include "src/hashmap.h"
+#include "src/list.h"
+#include "src/parsing/token.h"
+#include "src/unicode.h"
+#include "src/unicode-decoder.h"
+#include "src/utils.h"
+
+namespace v8 {
+namespace internal {
+
+
+class AstRawString;
+class AstValueFactory;
+class ParserRecorder;
+class UnicodeCache;
+
+
+// ---------------------------------------------------------------------
+// Buffered stream of UTF-16 code units, using an internal UTF-16 buffer.
+// A code unit is a 16 bit value representing either a 16 bit code point
+// or one part of a surrogate pair that make a single 21 bit code point.
+
+class Utf16CharacterStream {
+ public:
+  Utf16CharacterStream() : pos_(0) { }
+  virtual ~Utf16CharacterStream() { }
+
+  // Returns and advances past the next UTF-16 code unit in the input
+  // stream. If there are no more code units, it returns a negative
+  // value.
+  inline uc32 Advance() {
+    if (buffer_cursor_ < buffer_end_ || ReadBlock()) {
+      pos_++;
+      return static_cast<uc32>(*(buffer_cursor_++));
+    }
+    // Note: currently the following increment is necessary to avoid a
+    // parser problem! The scanner treats the final kEndOfInput as
+    // a code unit with a position, and does math relative to that
+    // position.
+    pos_++;
+
+    return kEndOfInput;
+  }
+
+  // Return the current position in the code unit stream.
+  // Starts at zero.
+  inline size_t pos() const { return pos_; }
+
+  // Skips forward past the next code_unit_count UTF-16 code units
+  // in the input, or until the end of input if that comes sooner.
+  // Returns the number of code units actually skipped. If less
+  // than code_unit_count,
+  inline size_t SeekForward(size_t code_unit_count) {
+    size_t buffered_chars = buffer_end_ - buffer_cursor_;
+    if (code_unit_count <= buffered_chars) {
+      buffer_cursor_ += code_unit_count;
+      pos_ += code_unit_count;
+      return code_unit_count;
+    }
+    return SlowSeekForward(code_unit_count);
+  }
+
+  // Pushes back the most recently read UTF-16 code unit (or negative
+  // value if at end of input), i.e., the value returned by the most recent
+  // call to Advance.
+  // Must not be used right after calling SeekForward.
+  virtual void PushBack(int32_t code_unit) = 0;
+
+  virtual bool SetBookmark();
+  virtual void ResetToBookmark();
+
+ protected:
+  static const uc32 kEndOfInput = -1;
+
+  // Ensures that the buffer_cursor_ points to the code_unit at
+  // position pos_ of the input, if possible. If the position
+  // is at or after the end of the input, return false. If there
+  // are more code_units available, return true.
+  virtual bool ReadBlock() = 0;
+  virtual size_t SlowSeekForward(size_t code_unit_count) = 0;
+
+  const uint16_t* buffer_cursor_;
+  const uint16_t* buffer_end_;
+  size_t pos_;
+};
+
+
+// ---------------------------------------------------------------------
+// DuplicateFinder discovers duplicate symbols.
+
+class DuplicateFinder {
+ public:
+  explicit DuplicateFinder(UnicodeCache* constants)
+      : unicode_constants_(constants),
+        backing_store_(16),
+        map_(&Match) { }
+
+  int AddOneByteSymbol(Vector<const uint8_t> key, int value);
+  int AddTwoByteSymbol(Vector<const uint16_t> key, int value);
+  // Add a a number literal by converting it (if necessary)
+  // to the string that ToString(ToNumber(literal)) would generate.
+  // and then adding that string with AddOneByteSymbol.
+  // This string is the actual value used as key in an object literal,
+  // and the one that must be different from the other keys.
+  int AddNumber(Vector<const uint8_t> key, int value);
+
+ private:
+  int AddSymbol(Vector<const uint8_t> key, bool is_one_byte, int value);
+  // Backs up the key and its length in the backing store.
+  // The backup is stored with a base 127 encoding of the
+  // length (plus a bit saying whether the string is one byte),
+  // followed by the bytes of the key.
+  uint8_t* BackupKey(Vector<const uint8_t> key, bool is_one_byte);
+
+  // Compare two encoded keys (both pointing into the backing store)
+  // for having the same base-127 encoded lengths and representation.
+  // and then having the same 'length' bytes following.
+  static bool Match(void* first, void* second);
+  // Creates a hash from a sequence of bytes.
+  static uint32_t Hash(Vector<const uint8_t> key, bool is_one_byte);
+  // Checks whether a string containing a JS number is its canonical
+  // form.
+  static bool IsNumberCanonical(Vector<const uint8_t> key);
+
+  // Size of buffer. Sufficient for using it to call DoubleToCString in
+  // from conversions.h.
+  static const int kBufferSize = 100;
+
+  UnicodeCache* unicode_constants_;
+  // Backing store used to store strings used as hashmap keys.
+  SequenceCollector<unsigned char> backing_store_;
+  HashMap map_;
+  // Buffer used for string->number->canonical string conversions.
+  char number_buffer_[kBufferSize];
+};
+
+
+// ----------------------------------------------------------------------------
+// LiteralBuffer -  Collector of chars of literals.
+
+class LiteralBuffer {
+ public:
+  LiteralBuffer() : is_one_byte_(true), position_(0), backing_store_() { }
+
+  ~LiteralBuffer() { backing_store_.Dispose(); }
+
+  INLINE(void AddChar(uint32_t code_unit)) {
+    if (position_ >= backing_store_.length()) ExpandBuffer();
+    if (is_one_byte_) {
+      if (code_unit <= unibrow::Latin1::kMaxChar) {
+        backing_store_[position_] = static_cast<byte>(code_unit);
+        position_ += kOneByteSize;
+        return;
+      }
+      ConvertToTwoByte();
+    }
+    if (code_unit <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
+      *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
+      position_ += kUC16Size;
+    } else {
+      *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
+          unibrow::Utf16::LeadSurrogate(code_unit);
+      position_ += kUC16Size;
+      if (position_ >= backing_store_.length()) ExpandBuffer();
+      *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
+          unibrow::Utf16::TrailSurrogate(code_unit);
+      position_ += kUC16Size;
+    }
+  }
+
+  bool is_one_byte() const { return is_one_byte_; }
+
+  bool is_contextual_keyword(Vector<const char> keyword) const {
+    return is_one_byte() && keyword.length() == position_ &&
+        (memcmp(keyword.start(), backing_store_.start(), position_) == 0);
+  }
+
+  Vector<const uint16_t> two_byte_literal() const {
+    DCHECK(!is_one_byte_);
+    DCHECK((position_ & 0x1) == 0);
+    return Vector<const uint16_t>(
+        reinterpret_cast<const uint16_t*>(backing_store_.start()),
+        position_ >> 1);
+  }
+
+  Vector<const uint8_t> one_byte_literal() const {
+    DCHECK(is_one_byte_);
+    return Vector<const uint8_t>(
+        reinterpret_cast<const uint8_t*>(backing_store_.start()),
+        position_);
+  }
+
+  int length() const {
+    return is_one_byte_ ? position_ : (position_ >> 1);
+  }
+
+  void ReduceLength(int delta) {
+    position_ -= delta * (is_one_byte_ ? kOneByteSize : kUC16Size);
+  }
+
+  void Reset() {
+    position_ = 0;
+    is_one_byte_ = true;
+  }
+
+  Handle<String> Internalize(Isolate* isolate) const;
+
+  void CopyFrom(const LiteralBuffer* other) {
+    if (other == nullptr) {
+      Reset();
+    } else {
+      is_one_byte_ = other->is_one_byte_;
+      position_ = other->position_;
+      backing_store_.Dispose();
+      backing_store_ = other->backing_store_.Clone();
+    }
+  }
+
+ private:
+  static const int kInitialCapacity = 16;
+  static const int kGrowthFactory = 4;
+  static const int kMinConversionSlack = 256;
+  static const int kMaxGrowth = 1 * MB;
+  inline int NewCapacity(int min_capacity) {
+    int capacity = Max(min_capacity, backing_store_.length());
+    int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
+    return new_capacity;
+  }
+
+  void ExpandBuffer() {
+    Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
+    MemCopy(new_store.start(), backing_store_.start(), position_);
+    backing_store_.Dispose();
+    backing_store_ = new_store;
+  }
+
+  void ConvertToTwoByte() {
+    DCHECK(is_one_byte_);
+    Vector<byte> new_store;
+    int new_content_size = position_ * kUC16Size;
+    if (new_content_size >= backing_store_.length()) {
+      // Ensure room for all currently read code units as UC16 as well
+      // as the code unit about to be stored.
+      new_store = Vector<byte>::New(NewCapacity(new_content_size));
+    } else {
+      new_store = backing_store_;
+    }
+    uint8_t* src = backing_store_.start();
+    uint16_t* dst = reinterpret_cast<uint16_t*>(new_store.start());
+    for (int i = position_ - 1; i >= 0; i--) {
+      dst[i] = src[i];
+    }
+    if (new_store.start() != backing_store_.start()) {
+      backing_store_.Dispose();
+      backing_store_ = new_store;
+    }
+    position_ = new_content_size;
+    is_one_byte_ = false;
+  }
+
+  bool is_one_byte_;
+  int position_;
+  Vector<byte> backing_store_;
+
+  DISALLOW_COPY_AND_ASSIGN(LiteralBuffer);
+};
+
+
+// ----------------------------------------------------------------------------
+// JavaScript Scanner.
+
+class Scanner {
+ public:
+  // Scoped helper for literal recording. Automatically drops the literal
+  // if aborting the scanning before it's complete.
+  class LiteralScope {
+   public:
+    explicit LiteralScope(Scanner* self) : scanner_(self), complete_(false) {
+      scanner_->StartLiteral();
+    }
+     ~LiteralScope() {
+       if (!complete_) scanner_->DropLiteral();
+     }
+    void Complete() {
+      complete_ = true;
+    }
+
+   private:
+    Scanner* scanner_;
+    bool complete_;
+  };
+
+  // Scoped helper for a re-settable bookmark.
+  class BookmarkScope {
+   public:
+    explicit BookmarkScope(Scanner* scanner) : scanner_(scanner) {
+      DCHECK_NOT_NULL(scanner_);
+    }
+    ~BookmarkScope() { scanner_->DropBookmark(); }
+
+    bool Set() { return scanner_->SetBookmark(); }
+    void Reset() { scanner_->ResetToBookmark(); }
+    bool HasBeenSet() { return scanner_->BookmarkHasBeenSet(); }
+    bool HasBeenReset() { return scanner_->BookmarkHasBeenReset(); }
+
+   private:
+    Scanner* scanner_;
+
+    DISALLOW_COPY_AND_ASSIGN(BookmarkScope);
+  };
+
+  // Representation of an interval of source positions.
+  struct Location {
+    Location(int b, int e) : beg_pos(b), end_pos(e) { }
+    Location() : beg_pos(0), end_pos(0) { }
+
+    bool IsValid() const {
+      return beg_pos >= 0 && end_pos >= beg_pos;
+    }
+
+    static Location invalid() { return Location(-1, -1); }
+
+    int beg_pos;
+    int end_pos;
+  };
+
+  // -1 is outside of the range of any real source code.
+  static const int kNoOctalLocation = -1;
+
+  explicit Scanner(UnicodeCache* scanner_contants);
+
+  void Initialize(Utf16CharacterStream* source);
+
+  // Returns the next token and advances input.
+  Token::Value Next();
+  // Returns the token following peek()
+  Token::Value PeekAhead();
+  // Returns the current token again.
+  Token::Value current_token() { return current_.token; }
+  // Returns the location information for the current token
+  // (the token last returned by Next()).
+  Location location() const { return current_.location; }
+
+  // Similar functions for the upcoming token.
+
+  // One token look-ahead (past the token returned by Next()).
+  Token::Value peek() const { return next_.token; }
+
+  Location peek_location() const { return next_.location; }
+
+  bool literal_contains_escapes() const {
+    return LiteralContainsEscapes(current_);
+  }
+  bool next_literal_contains_escapes() const {
+    return LiteralContainsEscapes(next_);
+  }
+  bool is_literal_contextual_keyword(Vector<const char> keyword) {
+    DCHECK_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->is_contextual_keyword(keyword);
+  }
+  bool is_next_contextual_keyword(Vector<const char> keyword) {
+    DCHECK_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->is_contextual_keyword(keyword);
+  }
+
+  const AstRawString* CurrentSymbol(AstValueFactory* ast_value_factory);
+  const AstRawString* NextSymbol(AstValueFactory* ast_value_factory);
+  const AstRawString* CurrentRawSymbol(AstValueFactory* ast_value_factory);
+
+  double DoubleValue();
+  bool ContainsDot();
+  bool LiteralMatches(const char* data, int length, bool allow_escapes = true) {
+    if (is_literal_one_byte() &&
+        literal_length() == length &&
+        (allow_escapes || !literal_contains_escapes())) {
+      const char* token =
+          reinterpret_cast<const char*>(literal_one_byte_string().start());
+      return !strncmp(token, data, length);
+    }
+    return false;
+  }
+  inline bool UnescapedLiteralMatches(const char* data, int length) {
+    return LiteralMatches(data, length, false);
+  }
+
+  void IsGetOrSet(bool* is_get, bool* is_set) {
+    if (is_literal_one_byte() &&
+        literal_length() == 3 &&
+        !literal_contains_escapes()) {
+      const char* token =
+          reinterpret_cast<const char*>(literal_one_byte_string().start());
+      *is_get = strncmp(token, "get", 3) == 0;
+      *is_set = !*is_get && strncmp(token, "set", 3) == 0;
+    }
+  }
+
+  int FindSymbol(DuplicateFinder* finder, int value);
+
+  UnicodeCache* unicode_cache() { return unicode_cache_; }
+
+  // Returns the location of the last seen octal literal.
+  Location octal_position() const { return octal_pos_; }
+  void clear_octal_position() { octal_pos_ = Location::invalid(); }
+
+  // Returns the value of the last smi that was scanned.
+  int smi_value() const { return current_.smi_value_; }
+
+  // Seek forward to the given position.  This operation does not
+  // work in general, for instance when there are pushed back
+  // characters, but works for seeking forward until simple delimiter
+  // tokens, which is what it is used for.
+  void SeekForward(int pos);
+
+  // Returns true if there was a line terminator before the peek'ed token,
+  // possibly inside a multi-line comment.
+  bool HasAnyLineTerminatorBeforeNext() const {
+    return has_line_terminator_before_next_ ||
+           has_multiline_comment_before_next_;
+  }
+
+  // Scans the input as a regular expression pattern, previous
+  // character(s) must be /(=). Returns true if a pattern is scanned.
+  bool ScanRegExpPattern(bool seen_equal);
+  // Scans the input as regular expression flags. Returns the flags on success.
+  Maybe<RegExp::Flags> ScanRegExpFlags();
+
+  // Scans the input as a template literal
+  Token::Value ScanTemplateStart();
+  Token::Value ScanTemplateContinuation();
+
+  const LiteralBuffer* source_url() const { return &source_url_; }
+  const LiteralBuffer* source_mapping_url() const {
+    return &source_mapping_url_;
+  }
+
+  bool IdentifierIsFutureStrictReserved(const AstRawString* string) const;
+
+ private:
+  // The current and look-ahead token.
+  struct TokenDesc {
+    Token::Value token;
+    Location location;
+    LiteralBuffer* literal_chars;
+    LiteralBuffer* raw_literal_chars;
+    int smi_value_;
+  };
+
+  static const int kCharacterLookaheadBufferSize = 1;
+
+  // Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
+  template <bool capture_raw>
+  uc32 ScanOctalEscape(uc32 c, int length);
+
+  // Call this after setting source_ to the input.
+  void Init() {
+    // Set c0_ (one character ahead)
+    STATIC_ASSERT(kCharacterLookaheadBufferSize == 1);
+    Advance();
+    // Initialize current_ to not refer to a literal.
+    current_.literal_chars = NULL;
+    current_.raw_literal_chars = NULL;
+    next_next_.token = Token::UNINITIALIZED;
+  }
+
+  // Support BookmarkScope functionality.
+  bool SetBookmark();
+  void ResetToBookmark();
+  bool BookmarkHasBeenSet();
+  bool BookmarkHasBeenReset();
+  void DropBookmark();
+  static void CopyTokenDesc(TokenDesc* to, TokenDesc* from);
+
+  // Literal buffer support
+  inline void StartLiteral() {
+    LiteralBuffer* free_buffer =
+        (current_.literal_chars == &literal_buffer0_)
+            ? &literal_buffer1_
+            : (current_.literal_chars == &literal_buffer1_) ? &literal_buffer2_
+                                                            : &literal_buffer0_;
+    free_buffer->Reset();
+    next_.literal_chars = free_buffer;
+  }
+
+  inline void StartRawLiteral() {
+    LiteralBuffer* free_buffer =
+        (current_.raw_literal_chars == &raw_literal_buffer0_)
+            ? &raw_literal_buffer1_
+            : (current_.raw_literal_chars == &raw_literal_buffer1_)
+                  ? &raw_literal_buffer2_
+                  : &raw_literal_buffer0_;
+    free_buffer->Reset();
+    next_.raw_literal_chars = free_buffer;
+  }
+
+  INLINE(void AddLiteralChar(uc32 c)) {
+    DCHECK_NOT_NULL(next_.literal_chars);
+    next_.literal_chars->AddChar(c);
+  }
+
+  INLINE(void AddRawLiteralChar(uc32 c)) {
+    DCHECK_NOT_NULL(next_.raw_literal_chars);
+    next_.raw_literal_chars->AddChar(c);
+  }
+
+  INLINE(void ReduceRawLiteralLength(int delta)) {
+    DCHECK_NOT_NULL(next_.raw_literal_chars);
+    next_.raw_literal_chars->ReduceLength(delta);
+  }
+
+  // Stops scanning of a literal and drop the collected characters,
+  // e.g., due to an encountered error.
+  inline void DropLiteral() {
+    next_.literal_chars = NULL;
+    next_.raw_literal_chars = NULL;
+  }
+
+  inline void AddLiteralCharAdvance() {
+    AddLiteralChar(c0_);
+    Advance();
+  }
+
+  // Low-level scanning support.
+  template <bool capture_raw = false, bool check_surrogate = true>
+  void Advance() {
+    if (capture_raw) {
+      AddRawLiteralChar(c0_);
+    }
+    c0_ = source_->Advance();
+    if (check_surrogate) HandleLeadSurrogate();
+  }
+
+  void HandleLeadSurrogate() {
+    if (unibrow::Utf16::IsLeadSurrogate(c0_)) {
+      uc32 c1 = source_->Advance();
+      if (!unibrow::Utf16::IsTrailSurrogate(c1)) {
+        source_->PushBack(c1);
+      } else {
+        c0_ = unibrow::Utf16::CombineSurrogatePair(c0_, c1);
+      }
+    }
+  }
+
+  void PushBack(uc32 ch) {
+    if (ch > static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
+      source_->PushBack(unibrow::Utf16::TrailSurrogate(c0_));
+      source_->PushBack(unibrow::Utf16::LeadSurrogate(c0_));
+    } else {
+      source_->PushBack(c0_);
+    }
+    c0_ = ch;
+  }
+
+  inline Token::Value Select(Token::Value tok) {
+    Advance();
+    return tok;
+  }
+
+  inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) {
+    Advance();
+    if (c0_ == next) {
+      Advance();
+      return then;
+    } else {
+      return else_;
+    }
+  }
+
+  // Returns the literal string, if any, for the current token (the
+  // token last returned by Next()). The string is 0-terminated.
+  // Literal strings are collected for identifiers, strings, numbers as well
+  // as for template literals. For template literals we also collect the raw
+  // form.
+  // These functions only give the correct result if the literal was scanned
+  // when a LiteralScope object is alive.
+  Vector<const uint8_t> literal_one_byte_string() {
+    DCHECK_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->one_byte_literal();
+  }
+  Vector<const uint16_t> literal_two_byte_string() {
+    DCHECK_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->two_byte_literal();
+  }
+  bool is_literal_one_byte() {
+    DCHECK_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->is_one_byte();
+  }
+  int literal_length() const {
+    DCHECK_NOT_NULL(current_.literal_chars);
+    return current_.literal_chars->length();
+  }
+  // Returns the literal string for the next token (the token that
+  // would be returned if Next() were called).
+  Vector<const uint8_t> next_literal_one_byte_string() {
+    DCHECK_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->one_byte_literal();
+  }
+  Vector<const uint16_t> next_literal_two_byte_string() {
+    DCHECK_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->two_byte_literal();
+  }
+  bool is_next_literal_one_byte() {
+    DCHECK_NOT_NULL(next_.literal_chars);
+    return next_.literal_chars->is_one_byte();
+  }
+  Vector<const uint8_t> raw_literal_one_byte_string() {
+    DCHECK_NOT_NULL(current_.raw_literal_chars);
+    return current_.raw_literal_chars->one_byte_literal();
+  }
+  Vector<const uint16_t> raw_literal_two_byte_string() {
+    DCHECK_NOT_NULL(current_.raw_literal_chars);
+    return current_.raw_literal_chars->two_byte_literal();
+  }
+  bool is_raw_literal_one_byte() {
+    DCHECK_NOT_NULL(current_.raw_literal_chars);
+    return current_.raw_literal_chars->is_one_byte();
+  }
+
+  template <bool capture_raw>
+  uc32 ScanHexNumber(int expected_length);
+  // Scan a number of any length but not bigger than max_value. For example, the
+  // number can be 000000001, so it's very long in characters but its value is
+  // small.
+  template <bool capture_raw>
+  uc32 ScanUnlimitedLengthHexNumber(int max_value);
+
+  // Scans a single JavaScript token.
+  void Scan();
+
+  bool SkipWhiteSpace();
+  Token::Value SkipSingleLineComment();
+  Token::Value SkipSourceURLComment();
+  void TryToParseSourceURLComment();
+  Token::Value SkipMultiLineComment();
+  // Scans a possible HTML comment -- begins with '<!'.
+  Token::Value ScanHtmlComment();
+
+  void ScanDecimalDigits();
+  Token::Value ScanNumber(bool seen_period);
+  Token::Value ScanIdentifierOrKeyword();
+  Token::Value ScanIdentifierSuffix(LiteralScope* literal, bool escaped);
+
+  Token::Value ScanString();
+
+  // Scans an escape-sequence which is part of a string and adds the
+  // decoded character to the current literal. Returns true if a pattern
+  // is scanned.
+  template <bool capture_raw, bool in_template_literal>
+  bool ScanEscape();
+
+  // Decodes a Unicode escape-sequence which is part of an identifier.
+  // If the escape sequence cannot be decoded the result is kBadChar.
+  uc32 ScanIdentifierUnicodeEscape();
+  // Helper for the above functions.
+  template <bool capture_raw>
+  uc32 ScanUnicodeEscape();
+
+  Token::Value ScanTemplateSpan();
+
+  // Return the current source position.
+  int source_pos() {
+    return static_cast<int>(source_->pos()) - kCharacterLookaheadBufferSize;
+  }
+
+  static bool LiteralContainsEscapes(const TokenDesc& token) {
+    Location location = token.location;
+    int source_length = (location.end_pos - location.beg_pos);
+    if (token.token == Token::STRING) {
+      // Subtract delimiters.
+      source_length -= 2;
+    }
+    return token.literal_chars->length() != source_length;
+  }
+
+  UnicodeCache* unicode_cache_;
+
+  // Buffers collecting literal strings, numbers, etc.
+  LiteralBuffer literal_buffer0_;
+  LiteralBuffer literal_buffer1_;
+  LiteralBuffer literal_buffer2_;
+
+  // Values parsed from magic comments.
+  LiteralBuffer source_url_;
+  LiteralBuffer source_mapping_url_;
+
+  // Buffer to store raw string values
+  LiteralBuffer raw_literal_buffer0_;
+  LiteralBuffer raw_literal_buffer1_;
+  LiteralBuffer raw_literal_buffer2_;
+
+  TokenDesc current_;    // desc for current token (as returned by Next())
+  TokenDesc next_;       // desc for next token (one token look-ahead)
+  TokenDesc next_next_;  // desc for the token after next (after PeakAhead())
+
+  // Variables for Scanner::BookmarkScope and the *Bookmark implementation.
+  // These variables contain the scanner state when a bookmark is set.
+  //
+  // We will use bookmark_c0_ as a 'control' variable, where:
+  // - bookmark_c0_ >= 0: A bookmark has been set and this contains c0_.
+  // - bookmark_c0_ == -1: No bookmark has been set.
+  // - bookmark_c0_ == -2: The bookmark has been applied (ResetToBookmark).
+  //
+  // Which state is being bookmarked? The parser state is distributed over
+  // several variables, roughly like this:
+  //   ...    1234        +       5678 ..... [character stream]
+  //       [current_] [next_] c0_ |      [scanner state]
+  // So when the scanner is logically at the beginning of an expression
+  // like "1234 + 4567", then:
+  // - current_ contains "1234"
+  // - next_ contains "+"
+  // - c0_ contains ' ' (the space between "+" and "5678",
+  // - the source_ character stream points to the beginning of "5678".
+  // To be able to restore this state, we will keep copies of current_, next_,
+  // and c0_; we'll ask the stream to bookmark itself, and we'll copy the
+  // contents of current_'s and next_'s literal buffers to bookmark_*_literal_.
+  static const uc32 kNoBookmark = -1;
+  static const uc32 kBookmarkWasApplied = -2;
+  uc32 bookmark_c0_;
+  TokenDesc bookmark_current_;
+  TokenDesc bookmark_next_;
+  LiteralBuffer bookmark_current_literal_;
+  LiteralBuffer bookmark_current_raw_literal_;
+  LiteralBuffer bookmark_next_literal_;
+  LiteralBuffer bookmark_next_raw_literal_;
+
+  // Input stream. Must be initialized to an Utf16CharacterStream.
+  Utf16CharacterStream* source_;
+
+
+  // Start position of the octal literal last scanned.
+  Location octal_pos_;
+
+  // One Unicode character look-ahead; c0_ < 0 at the end of the input.
+  uc32 c0_;
+
+  // Whether there is a line terminator whitespace character after
+  // the current token, and  before the next. Does not count newlines
+  // inside multiline comments.
+  bool has_line_terminator_before_next_;
+  // Whether there is a multi-line comment that contains a
+  // line-terminator after the current token, and before the next.
+  bool has_multiline_comment_before_next_;
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_SCANNER_H_
diff --git a/src/parsing/token.cc b/src/parsing/token.cc
new file mode 100644
index 0000000..7edfefa
--- /dev/null
+++ b/src/parsing/token.cc
@@ -0,0 +1,42 @@
+// Copyright 2006-2008 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.
+
+#include <stdint.h>
+
+#include "src/parsing/token.h"
+
+namespace v8 {
+namespace internal {
+
+#define T(name, string, precedence) #name,
+const char* const Token::name_[NUM_TOKENS] = {
+  TOKEN_LIST(T, T)
+};
+#undef T
+
+
+#define T(name, string, precedence) string,
+const char* const Token::string_[NUM_TOKENS] = {
+  TOKEN_LIST(T, T)
+};
+#undef T
+
+
+#define T(name, string, precedence) precedence,
+const int8_t Token::precedence_[NUM_TOKENS] = {
+  TOKEN_LIST(T, T)
+};
+#undef T
+
+
+#define KT(a, b, c) 'T',
+#define KK(a, b, c) 'K',
+const char Token::token_type[] = {
+  TOKEN_LIST(KT, KK)
+};
+#undef KT
+#undef KK
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/parsing/token.h b/src/parsing/token.h
new file mode 100644
index 0000000..fee1f7e
--- /dev/null
+++ b/src/parsing/token.h
@@ -0,0 +1,324 @@
+// 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_TOKEN_H_
+#define V8_PARSING_TOKEN_H_
+
+#include "src/base/logging.h"
+#include "src/globals.h"
+
+namespace v8 {
+namespace internal {
+
+// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the
+// same signature M(name, string, precedence), where name is the
+// symbolic token name, string is the corresponding syntactic symbol
+// (or NULL, for literals), and precedence is the precedence (or 0).
+// The parameters are invoked for token categories as follows:
+//
+//   T: Non-keyword tokens
+//   K: Keyword tokens
+
+// IGNORE_TOKEN is a convenience macro that can be supplied as
+// an argument (at any position) for a TOKEN_LIST call. It does
+// nothing with tokens belonging to the respective category.
+
+#define IGNORE_TOKEN(name, string, precedence)
+
+#define TOKEN_LIST(T, K)                                             \
+  /* End of source indicator. */                                     \
+  T(EOS, "EOS", 0)                                                   \
+                                                                     \
+  /* Punctuators (ECMA-262, section 7.7, page 15). */                \
+  T(LPAREN, "(", 0)                                                  \
+  T(RPAREN, ")", 0)                                                  \
+  T(LBRACK, "[", 0)                                                  \
+  T(RBRACK, "]", 0)                                                  \
+  T(LBRACE, "{", 0)                                                  \
+  T(RBRACE, "}", 0)                                                  \
+  T(COLON, ":", 0)                                                   \
+  T(SEMICOLON, ";", 0)                                               \
+  T(PERIOD, ".", 0)                                                  \
+  T(ELLIPSIS, "...", 0)                                              \
+  T(CONDITIONAL, "?", 3)                                             \
+  T(INC, "++", 0)                                                    \
+  T(DEC, "--", 0)                                                    \
+  T(ARROW, "=>", 0)                                                  \
+                                                                     \
+  /* Assignment operators. */                                        \
+  /* IsAssignmentOp() and Assignment::is_compound() relies on */     \
+  /* this block of enum values being contiguous and sorted in the */ \
+  /* same order! */                                                  \
+  T(INIT, "=init", 2) /* AST-use only. */                            \
+  T(ASSIGN, "=", 2)                                                  \
+  T(ASSIGN_BIT_OR, "|=", 2)                                          \
+  T(ASSIGN_BIT_XOR, "^=", 2)                                         \
+  T(ASSIGN_BIT_AND, "&=", 2)                                         \
+  T(ASSIGN_SHL, "<<=", 2)                                            \
+  T(ASSIGN_SAR, ">>=", 2)                                            \
+  T(ASSIGN_SHR, ">>>=", 2)                                           \
+  T(ASSIGN_ADD, "+=", 2)                                             \
+  T(ASSIGN_SUB, "-=", 2)                                             \
+  T(ASSIGN_MUL, "*=", 2)                                             \
+  T(ASSIGN_DIV, "/=", 2)                                             \
+  T(ASSIGN_MOD, "%=", 2)                                             \
+                                                                     \
+  /* Binary operators sorted by precedence. */                       \
+  /* IsBinaryOp() relies on this block of enum values */             \
+  /* being contiguous and sorted in the same order! */               \
+  T(COMMA, ",", 1)                                                   \
+  T(OR, "||", 4)                                                     \
+  T(AND, "&&", 5)                                                    \
+  T(BIT_OR, "|", 6)                                                  \
+  T(BIT_XOR, "^", 7)                                                 \
+  T(BIT_AND, "&", 8)                                                 \
+  T(SHL, "<<", 11)                                                   \
+  T(SAR, ">>", 11)                                                   \
+  T(SHR, ">>>", 11)                                                  \
+  T(ROR, "rotate right", 11) /* only used by Crankshaft */           \
+  T(ADD, "+", 12)                                                    \
+  T(SUB, "-", 12)                                                    \
+  T(MUL, "*", 13)                                                    \
+  T(DIV, "/", 13)                                                    \
+  T(MOD, "%", 13)                                                    \
+                                                                     \
+  /* Compare operators sorted by precedence. */                      \
+  /* IsCompareOp() relies on this block of enum values */            \
+  /* being contiguous and sorted in the same order! */               \
+  T(EQ, "==", 9)                                                     \
+  T(NE, "!=", 9)                                                     \
+  T(EQ_STRICT, "===", 9)                                             \
+  T(NE_STRICT, "!==", 9)                                             \
+  T(LT, "<", 10)                                                     \
+  T(GT, ">", 10)                                                     \
+  T(LTE, "<=", 10)                                                   \
+  T(GTE, ">=", 10)                                                   \
+  K(INSTANCEOF, "instanceof", 10)                                    \
+  K(IN, "in", 10)                                                    \
+                                                                     \
+  /* Unary operators. */                                             \
+  /* IsUnaryOp() relies on this block of enum values */              \
+  /* being contiguous and sorted in the same order! */               \
+  T(NOT, "!", 0)                                                     \
+  T(BIT_NOT, "~", 0)                                                 \
+  K(DELETE, "delete", 0)                                             \
+  K(TYPEOF, "typeof", 0)                                             \
+  K(VOID, "void", 0)                                                 \
+                                                                     \
+  /* Keywords (ECMA-262, section 7.5.2, page 13). */                 \
+  K(BREAK, "break", 0)                                               \
+  K(CASE, "case", 0)                                                 \
+  K(CATCH, "catch", 0)                                               \
+  K(CONTINUE, "continue", 0)                                         \
+  K(DEBUGGER, "debugger", 0)                                         \
+  K(DEFAULT, "default", 0)                                           \
+  /* DELETE */                                                       \
+  K(DO, "do", 0)                                                     \
+  K(ELSE, "else", 0)                                                 \
+  K(FINALLY, "finally", 0)                                           \
+  K(FOR, "for", 0)                                                   \
+  K(FUNCTION, "function", 0)                                         \
+  K(IF, "if", 0)                                                     \
+  /* IN */                                                           \
+  /* INSTANCEOF */                                                   \
+  K(NEW, "new", 0)                                                   \
+  K(RETURN, "return", 0)                                             \
+  K(SWITCH, "switch", 0)                                             \
+  K(THIS, "this", 0)                                                 \
+  K(THROW, "throw", 0)                                               \
+  K(TRY, "try", 0)                                                   \
+  /* TYPEOF */                                                       \
+  K(VAR, "var", 0)                                                   \
+  /* VOID */                                                         \
+  K(WHILE, "while", 0)                                               \
+  K(WITH, "with", 0)                                                 \
+                                                                     \
+  /* Literals (ECMA-262, section 7.8, page 16). */                   \
+  K(NULL_LITERAL, "null", 0)                                         \
+  K(TRUE_LITERAL, "true", 0)                                         \
+  K(FALSE_LITERAL, "false", 0)                                       \
+  T(NUMBER, NULL, 0)                                                 \
+  T(SMI, NULL, 0)                                                    \
+  T(STRING, NULL, 0)                                                 \
+                                                                     \
+  /* Identifiers (not keywords or future reserved words). */         \
+  T(IDENTIFIER, NULL, 0)                                             \
+                                                                     \
+  /* Future reserved words (ECMA-262, section 7.6.1.2). */           \
+  T(FUTURE_RESERVED_WORD, NULL, 0)                                   \
+  T(FUTURE_STRICT_RESERVED_WORD, NULL, 0)                            \
+  K(CLASS, "class", 0)                                               \
+  K(CONST, "const", 0)                                               \
+  K(EXPORT, "export", 0)                                             \
+  K(EXTENDS, "extends", 0)                                           \
+  K(IMPORT, "import", 0)                                             \
+  K(LET, "let", 0)                                                   \
+  K(STATIC, "static", 0)                                             \
+  K(YIELD, "yield", 0)                                               \
+  K(SUPER, "super", 0)                                               \
+                                                                     \
+  /* Illegal token - not able to scan. */                            \
+  T(ILLEGAL, "ILLEGAL", 0)                                           \
+  T(ESCAPED_KEYWORD, NULL, 0)                                        \
+  T(ESCAPED_STRICT_RESERVED_WORD, NULL, 0)                           \
+                                                                     \
+  /* Scanner-internal use only. */                                   \
+  T(WHITESPACE, NULL, 0)                                             \
+  T(UNINITIALIZED, NULL, 0)                                          \
+                                                                     \
+  /* ES6 Template Literals */                                        \
+  T(TEMPLATE_SPAN, NULL, 0)                                          \
+  T(TEMPLATE_TAIL, NULL, 0)
+
+
+class Token {
+ public:
+  // All token values.
+#define T(name, string, precedence) name,
+  enum Value {
+    TOKEN_LIST(T, T)
+    NUM_TOKENS
+  };
+#undef T
+
+  // Returns a string corresponding to the C++ token name
+  // (e.g. "LT" for the token LT).
+  static const char* Name(Value tok) {
+    DCHECK(tok < NUM_TOKENS);  // tok is unsigned
+    return name_[tok];
+  }
+
+  // Predicates
+  static bool IsKeyword(Value tok) {
+    return token_type[tok] == 'K';
+  }
+
+  static bool IsIdentifier(Value tok, LanguageMode language_mode,
+                           bool is_generator) {
+    switch (tok) {
+      case IDENTIFIER:
+        return true;
+      case ESCAPED_STRICT_RESERVED_WORD:
+      case FUTURE_STRICT_RESERVED_WORD:
+      case LET:
+      case STATIC:
+        return is_sloppy(language_mode);
+      case YIELD:
+        return !is_generator && is_sloppy(language_mode);
+      default:
+        return false;
+    }
+    UNREACHABLE();
+    return false;
+  }
+
+  static bool IsAssignmentOp(Value tok) {
+    return INIT <= tok && tok <= ASSIGN_MOD;
+  }
+
+  static bool IsBinaryOp(Value op) {
+    return COMMA <= op && op <= MOD;
+  }
+
+  static bool IsTruncatingBinaryOp(Value op) {
+    return BIT_OR <= op && op <= ROR;
+  }
+
+  static bool IsCompareOp(Value op) {
+    return EQ <= op && op <= IN;
+  }
+
+  static bool IsOrderedRelationalCompareOp(Value op) {
+    return op == LT || op == LTE || op == GT || op == GTE;
+  }
+
+  static bool IsEqualityOp(Value op) {
+    return op == EQ || op == EQ_STRICT;
+  }
+
+  static bool IsInequalityOp(Value op) {
+    return op == NE || op == NE_STRICT;
+  }
+
+  static bool IsArithmeticCompareOp(Value op) {
+    return IsOrderedRelationalCompareOp(op) ||
+        IsEqualityOp(op) || IsInequalityOp(op);
+  }
+
+  static Value NegateCompareOp(Value op) {
+    DCHECK(IsArithmeticCompareOp(op));
+    switch (op) {
+      case EQ: return NE;
+      case NE: return EQ;
+      case EQ_STRICT: return NE_STRICT;
+      case NE_STRICT: return EQ_STRICT;
+      case LT: return GTE;
+      case GT: return LTE;
+      case LTE: return GT;
+      case GTE: return LT;
+      default:
+        UNREACHABLE();
+        return op;
+    }
+  }
+
+  static Value ReverseCompareOp(Value op) {
+    DCHECK(IsArithmeticCompareOp(op));
+    switch (op) {
+      case EQ: return EQ;
+      case NE: return NE;
+      case EQ_STRICT: return EQ_STRICT;
+      case NE_STRICT: return NE_STRICT;
+      case LT: return GT;
+      case GT: return LT;
+      case LTE: return GTE;
+      case GTE: return LTE;
+      default:
+        UNREACHABLE();
+        return op;
+    }
+  }
+
+  static bool IsBitOp(Value op) {
+    return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
+  }
+
+  static bool IsUnaryOp(Value op) {
+    return (NOT <= op && op <= VOID) || op == ADD || op == SUB;
+  }
+
+  static bool IsCountOp(Value op) {
+    return op == INC || op == DEC;
+  }
+
+  static bool IsShiftOp(Value op) {
+    return (SHL <= op) && (op <= SHR);
+  }
+
+  // Returns a string corresponding to the JS token string
+  // (.e., "<" for the token LT) or NULL if the token doesn't
+  // have a (unique) string (e.g. an IDENTIFIER).
+  static const char* String(Value tok) {
+    DCHECK(tok < NUM_TOKENS);  // tok is unsigned.
+    return string_[tok];
+  }
+
+  // Returns the precedence > 0 for binary and compare
+  // operators; returns 0 otherwise.
+  static int Precedence(Value tok) {
+    DCHECK(tok < NUM_TOKENS);  // tok is unsigned.
+    return precedence_[tok];
+  }
+
+ private:
+  static const char* const name_[NUM_TOKENS];
+  static const char* const string_[NUM_TOKENS];
+  static const int8_t precedence_[NUM_TOKENS];
+  static const char token_type[NUM_TOKENS];
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PARSING_TOKEN_H_
