// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "v8.h"

#include "api.h"
#include "ast.h"
#include "bootstrapper.h"
#include "compiler.h"
#include "platform.h"
#include "runtime.h"
#include "parser.h"
#include "scopes.h"
#include "string-stream.h"

namespace v8 {
namespace internal {

class ParserFactory;
class ParserLog;
class TemporaryScope;
class Target;

template <typename T> class ZoneListWrapper;


// PositionStack is used for on-stack allocation of token positions for
// new expressions. Please look at ParseNewExpression.

class PositionStack  {
 public:
  explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
  ~PositionStack() { ASSERT(!*ok_ || is_empty()); }

  class Element  {
   public:
    Element(PositionStack* stack, int value) {
      previous_ = stack->top();
      value_ = value;
      stack->set_top(this);
    }

   private:
    Element* previous() { return previous_; }
    int value() { return value_; }
    friend class PositionStack;
    Element* previous_;
    int value_;
  };

  bool is_empty() { return top_ == NULL; }
  int pop() {
    ASSERT(!is_empty());
    int result = top_->value();
    top_ = top_->previous();
    return result;
  }

 private:
  Element* top() { return top_; }
  void set_top(Element* value) { top_ = value; }
  Element* top_;
  bool* ok_;
};


class Parser {
 public:
  Parser(Handle<Script> script, bool allow_natives_syntax,
         v8::Extension* extension, bool is_pre_parsing,
         ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
  virtual ~Parser() { }

  // Pre-parse the program from the character stream; returns true on
  // success, false if a stack-overflow happened during parsing.
  bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);

  void ReportMessage(const char* message, Vector<const char*> args);
  virtual void ReportMessageAt(Scanner::Location loc,
                               const char* message,
                               Vector<const char*> args) = 0;


  // Returns NULL if parsing failed.
  FunctionLiteral* ParseProgram(Handle<String> source,
                                unibrow::CharacterStream* stream,
                                bool in_global_context);
  FunctionLiteral* ParseLazy(Handle<String> source,
                             Handle<String> name,
                             int start_position, bool is_expression);

  // The minimum number of contiguous assignment that will
  // be treated as an initialization block. Benchmarks show that
  // the overhead exceeds the savings below this limit.
  static const int kMinInitializationBlock = 3;

 protected:

  enum Mode {
    PARSE_LAZILY,
    PARSE_EAGERLY
  };

  // Report syntax error
  void ReportUnexpectedToken(Token::Value token);

  Handle<Script> script_;
  Scanner scanner_;

  Scope* top_scope_;
  int with_nesting_level_;

  TemporaryScope* temp_scope_;
  Mode mode_;

  Target* target_stack_;  // for break, continue statements
  bool allow_natives_syntax_;
  v8::Extension* extension_;
  ParserFactory* factory_;
  ParserLog* log_;
  bool is_pre_parsing_;
  ScriptDataImpl* pre_data_;

  bool inside_with() const  { return with_nesting_level_ > 0; }
  ParserFactory* factory() const  { return factory_; }
  ParserLog* log() const { return log_; }
  Scanner& scanner()  { return scanner_; }
  Mode mode() const  { return mode_; }
  ScriptDataImpl* pre_data() const  { return pre_data_; }

  // 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* ParseSourceElements(ZoneListWrapper<Statement>* processor,
                            int end_token, bool* ok);
  Statement* ParseStatement(ZoneStringList* labels, bool* ok);
  Statement* ParseFunctionDeclaration(bool* ok);
  Statement* ParseNativeDeclaration(bool* ok);
  Block* ParseBlock(ZoneStringList* labels, bool* ok);
  Block* ParseVariableStatement(bool* ok);
  Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok);
  Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
                                                bool* ok);
  IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
  Statement* ParseContinueStatement(bool* ok);
  Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
  Statement* ParseReturnStatement(bool* ok);
  Block* WithHelper(Expression* obj,
                    ZoneStringList* labels,
                    bool is_catch_block,
                    bool* ok);
  Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
  CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
  SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
  DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
  WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
  Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
  Statement* ParseThrowStatement(bool* ok);
  Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
  TryStatement* ParseTryStatement(bool* ok);
  DebuggerStatement* ParseDebuggerStatement(bool* ok);

  Expression* ParseExpression(bool accept_IN, bool* ok);
  Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
  Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
  Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
  Expression* ParseUnaryExpression(bool* ok);
  Expression* ParsePostfixExpression(bool* ok);
  Expression* ParseLeftHandSideExpression(bool* ok);
  Expression* ParseNewExpression(bool* ok);
  Expression* ParseMemberExpression(bool* ok);
  Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
  Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
                                                   bool* ok);
  Expression* ParsePrimaryExpression(bool* ok);
  Expression* ParseArrayLiteral(bool* ok);
  Expression* ParseObjectLiteral(bool* ok);
  Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);

  // Decide if a property should be the object boilerplate.
  bool IsBoilerplateProperty(ObjectLiteral::Property* property);
  // If the expression is a literal, return the literal value;
  // if the expression is a materialized literal and is simple return a
  // compile time value as encoded by CompileTimeValue::GetValue().
  // Otherwise, return undefined literal as the placeholder
  // in the object literal boilerplate.
  Handle<Object> GetBoilerplateValue(Expression* expression);

  enum FunctionLiteralType {
    EXPRESSION,
    DECLARATION,
    NESTED
  };

  ZoneList<Expression*>* ParseArguments(bool* ok);
  FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
                                        int function_token_position,
                                        FunctionLiteralType type,
                                        bool* ok);


  // Magical syntax support.
  Expression* ParseV8Intrinsic(bool* ok);

  INLINE(Token::Value peek()) { return scanner_.peek(); }
  INLINE(Token::Value Next()) { return scanner_.Next(); }
  INLINE(void Consume(Token::Value token));
  void Expect(Token::Value token, bool* ok);
  void ExpectSemicolon(bool* ok);

  // Get odd-ball literals.
  Literal* GetLiteralUndefined();
  Literal* GetLiteralTheHole();
  Literal* GetLiteralNumber(double value);

  Handle<String> ParseIdentifier(bool* ok);
  Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
                                           bool* is_set,
                                           bool* ok);

  // Parser support
  virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
                                 FunctionLiteral* fun,
                                 bool resolve,
                                 bool* ok) = 0;

  bool TargetStackContainsLabel(Handle<String> label);
  BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
  IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);

  void RegisterTargetUse(BreakTarget* target, Target* stop);

  // Create a number literal.
  Literal* NewNumberLiteral(double value);

  // Generate AST node that throw a ReferenceError with the given type.
  Expression* NewThrowReferenceError(Handle<String> type);

  // Generate AST node that throw 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(Handle<String> type, Handle<Object> first);

  // Generate AST node that throw a TypeError with the given
  // type. Both arguments must be non-null (in the handle sense).
  Expression* NewThrowTypeError(Handle<String> type,
                                Handle<Object> first,
                                Handle<Object> second);

  // Generic AST generator for throwing errors from compiled code.
  Expression* NewThrowError(Handle<String> constructor,
                            Handle<String> type,
                            Vector< Handle<Object> > arguments);

  friend class Target;
  friend class TargetScope;
  friend class LexicalScope;
  friend class TemporaryScope;
};


template <typename T, int initial_size>
class BufferedZoneList {
 public:

  BufferedZoneList() :
    list_(NULL), last_(NULL) {}

  // Adds element at end of list. This element is buffered and can
  // be read using last() or removed using RemoveLast until a new Add or until
  // RemoveLast or GetList has been called.
  void Add(T* value) {
    if (last_ != NULL) {
      if (list_ == NULL) {
        list_ = new ZoneList<T*>(initial_size);
      }
      list_->Add(last_);
    }
    last_ = value;
  }

  T* last() {
    ASSERT(last_ != NULL);
    return last_;
  }

  T* RemoveLast() {
    ASSERT(last_ != NULL);
    T* result = last_;
    if (list_ != NULL && list_->length() > 0)
      last_ = list_->RemoveLast();
    else
      last_ = NULL;
    return result;
  }

  T* Get(int i) {
    ASSERT(0 <= i && i < length());
    if (list_ == NULL) {
      ASSERT_EQ(0, i);
      return last_;
    } else {
      if (i == list_->length()) {
        ASSERT(last_ != NULL);
        return last_;
      } else {
        return list_->at(i);
      }
    }
  }

  void Clear() {
    list_ = NULL;
    last_ = NULL;
  }

  int length() {
    int length = (list_ == NULL) ? 0 : list_->length();
    return length + ((last_ == NULL) ? 0 : 1);
  }

  ZoneList<T*>* GetList() {
    if (list_ == NULL) {
      list_ = new ZoneList<T*>(initial_size);
    }
    if (last_ != NULL) {
      list_->Add(last_);
      last_ = NULL;
    }
    return list_;
  }

 private:
  ZoneList<T*>* list_;
  T* last_;
};

// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
class RegExpBuilder: public ZoneObject {
 public:
  RegExpBuilder();
  void AddCharacter(uc16 character);
  // "Adds" an empty expression. Does nothing except consume a
  // following quantifier
  void AddEmpty();
  void AddAtom(RegExpTree* tree);
  void AddAssertion(RegExpTree* tree);
  void NewAlternative();  // '|'
  void AddQuantifierToAtom(int min, int max, bool is_greedy);
  RegExpTree* ToRegExp();
 private:
  void FlushCharacters();
  void FlushText();
  void FlushTerms();
  bool pending_empty_;
  ZoneList<uc16>* characters_;
  BufferedZoneList<RegExpTree, 2> terms_;
  BufferedZoneList<RegExpTree, 2> text_;
  BufferedZoneList<RegExpTree, 2> alternatives_;
#ifdef DEBUG
  enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_;
#define LAST(x) last_added_ = x;
#else
#define LAST(x)
#endif
};


RegExpBuilder::RegExpBuilder()
  : pending_empty_(false),
    characters_(NULL),
    terms_(),
    alternatives_()
#ifdef DEBUG
  , last_added_(ADD_NONE)
#endif
  {}


void RegExpBuilder::FlushCharacters() {
  pending_empty_ = false;
  if (characters_ != NULL) {
    RegExpTree* atom = new RegExpAtom(characters_->ToConstVector());
    characters_ = NULL;
    text_.Add(atom);
    LAST(ADD_ATOM);
  }
}


void RegExpBuilder::FlushText() {
  FlushCharacters();
  int num_text = text_.length();
  if (num_text == 0) {
    return;
  } else if (num_text == 1) {
    terms_.Add(text_.last());
  } else {
    RegExpText* text = new RegExpText();
    for (int i = 0; i < num_text; i++)
      text_.Get(i)->AppendToText(text);
    terms_.Add(text);
  }
  text_.Clear();
}


void RegExpBuilder::AddCharacter(uc16 c) {
  pending_empty_ = false;
  if (characters_ == NULL) {
    characters_ = new ZoneList<uc16>(4);
  }
  characters_->Add(c);
  LAST(ADD_CHAR);
}


void RegExpBuilder::AddEmpty() {
  pending_empty_ = true;
}


void RegExpBuilder::AddAtom(RegExpTree* term) {
  if (term->IsEmpty()) {
    AddEmpty();
    return;
  }
  if (term->IsTextElement()) {
    FlushCharacters();
    text_.Add(term);
  } else {
    FlushText();
    terms_.Add(term);
  }
  LAST(ADD_ATOM);
}


void RegExpBuilder::AddAssertion(RegExpTree* assert) {
  FlushText();
  terms_.Add(assert);
  LAST(ADD_ASSERT);
}


void RegExpBuilder::NewAlternative() {
  FlushTerms();
}


void RegExpBuilder::FlushTerms() {
  FlushText();
  int num_terms = terms_.length();
  RegExpTree* alternative;
  if (num_terms == 0) {
    alternative = RegExpEmpty::GetInstance();
  } else if (num_terms == 1) {
    alternative = terms_.last();
  } else {
    alternative = new RegExpAlternative(terms_.GetList());
  }
  alternatives_.Add(alternative);
  terms_.Clear();
  LAST(ADD_NONE);
}


RegExpTree* RegExpBuilder::ToRegExp() {
  FlushTerms();
  int num_alternatives = alternatives_.length();
  if (num_alternatives == 0) {
    return RegExpEmpty::GetInstance();
  }
  if (num_alternatives == 1) {
    return alternatives_.last();
  }
  return new RegExpDisjunction(alternatives_.GetList());
}


void RegExpBuilder::AddQuantifierToAtom(int min, int max, bool is_greedy) {
  if (pending_empty_) {
    pending_empty_ = false;
    return;
  }
  RegExpTree* atom;
  if (characters_ != NULL) {
    ASSERT(last_added_ == ADD_CHAR);
    // Last atom was character.
    Vector<const uc16> char_vector = characters_->ToConstVector();
    int num_chars = char_vector.length();
    if (num_chars > 1) {
      Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
      text_.Add(new RegExpAtom(prefix));
      char_vector = char_vector.SubVector(num_chars - 1, num_chars);
    }
    characters_ = NULL;
    atom = new RegExpAtom(char_vector);
    FlushText();
  } else if (text_.length() > 0) {
    ASSERT(last_added_ == ADD_ATOM);
    atom = text_.RemoveLast();
    FlushText();
  } else if (terms_.length() > 0) {
    ASSERT(last_added_ == ADD_ATOM);
    atom = terms_.RemoveLast();
    if (atom->max_match() == 0) {
      // Guaranteed to only match an empty string.
      LAST(ADD_TERM);
      if (min == 0) {
        return;
      }
      terms_.Add(atom);
      return;
    }
  } else {
    // Only call immediately after adding an atom or character!
    UNREACHABLE();
    return;
  }
  terms_.Add(new RegExpQuantifier(min, max, is_greedy, atom));
  LAST(ADD_TERM);
}


class RegExpParser {
 public:
  RegExpParser(FlatStringReader* in,
               Handle<String>* error,
               bool multiline_mode);
  RegExpTree* ParsePattern();
  RegExpTree* ParseDisjunction();
  RegExpTree* ParseGroup();
  RegExpTree* ParseCharacterClass();

  // Parses a {...,...} quantifier and stores the range in the given
  // out parameters.
  bool ParseIntervalQuantifier(int* min_out, int* max_out);

  // Parses and returns a single escaped character.  The character
  // must not be 'b' or 'B' since they are usually handle specially.
  uc32 ParseClassCharacterEscape();

  // Checks whether the following is a length-digit hexadecimal number,
  // and sets the value if it is.
  bool ParseHexEscape(int length, uc32* value);

  uc32 ParseControlLetterEscape();
  uc32 ParseOctalLiteral();

  // Tries to parse the input as a back reference.  If successful it
  // stores the result in the output parameter and returns true.  If
  // it fails it will push back the characters read so the same characters
  // can be reparsed.
  bool ParseBackReferenceIndex(int* index_out);

  CharacterRange ParseClassAtom(uc16* char_class);
  RegExpTree* ReportError(Vector<const char> message);
  void Advance();
  void Advance(int dist);
  void Reset(int pos);

  // Reports whether the pattern might be used as a literal search string.
  // Only use if the result of the parse is a single atom node.
  bool simple();
  bool contains_anchor() { return contains_anchor_; }
  void set_contains_anchor() { contains_anchor_ = true; }
  int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
  int position() { return next_pos_ - 1; }
  bool failed() { return failed_; }

  static const int kMaxCaptures = 1 << 16;
  static const uc32 kEndMarker = (1 << 21);
 private:
  enum SubexpressionType {
    INITIAL,
    CAPTURE,  // All positive values represent captures.
    POSITIVE_LOOKAHEAD,
    NEGATIVE_LOOKAHEAD,
    GROUPING
  };

  class RegExpParserState : public ZoneObject {
   public:
    RegExpParserState(RegExpParserState* previous_state,
                      SubexpressionType group_type,
                      int disjunction_capture_index)
        : previous_state_(previous_state),
          builder_(new RegExpBuilder()),
          group_type_(group_type),
          disjunction_capture_index_(disjunction_capture_index) {}
    // Parser state of containing expression, if any.
    RegExpParserState* previous_state() { return previous_state_; }
    bool IsSubexpression() { return previous_state_ != NULL; }
    // RegExpBuilder building this regexp's AST.
    RegExpBuilder* builder() { return builder_; }
    // Type of regexp being parsed (parenthesized group or entire regexp).
    SubexpressionType group_type() { return group_type_; }
    // Index in captures array of first capture in this sub-expression, if any.
    // Also the capture index of this sub-expression itself, if group_type
    // is CAPTURE.
    int capture_index() { return disjunction_capture_index_; }
   private:
    // Linked list implementation of stack of states.
    RegExpParserState* previous_state_;
    // Builder for the stored disjunction.
    RegExpBuilder* builder_;
    // Stored disjunction type (capture, look-ahead or grouping), if any.
    SubexpressionType group_type_;
    // Stored disjunction's capture index (if any).
    int disjunction_capture_index_;
  };

  uc32 current() { return current_; }
  bool has_more() { return has_more_; }
  bool has_next() { return next_pos_ < in()->length(); }
  uc32 Next();
  FlatStringReader* in() { return in_; }
  void ScanForCaptures();
  uc32 current_;
  bool has_more_;
  bool multiline_;
  int next_pos_;
  FlatStringReader* in_;
  Handle<String>* error_;
  bool simple_;
  bool contains_anchor_;
  ZoneList<RegExpCapture*>* captures_;
  bool is_scanned_for_captures_;
  // The capture count is only valid after we have scanned for captures.
  int capture_count_;
  bool failed_;
};


// A temporary scope stores information during parsing, just like
// a plain scope.  However, temporary scopes are not kept around
// after parsing or referenced by syntax trees so they can be stack-
// allocated and hence used by the pre-parser.
class TemporaryScope BASE_EMBEDDED {
 public:
  explicit TemporaryScope(Parser* parser);
  ~TemporaryScope();

  int NextMaterializedLiteralIndex() {
    int next_index =
        materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
    materialized_literal_count_++;
    return next_index;
  }
  int materialized_literal_count() { return materialized_literal_count_; }

  void SetThisPropertyAssignmentInfo(
      bool only_this_property_assignments,
      bool only_simple_this_property_assignments,
      Handle<FixedArray> this_property_assignments) {
    only_this_property_assignments_ = only_this_property_assignments;
    only_simple_this_property_assignments_ =
        only_simple_this_property_assignments;
    this_property_assignments_ = this_property_assignments;
  }
  bool only_this_property_assignments() {
    return only_this_property_assignments_;
  }
  bool only_simple_this_property_assignments() {
    return only_simple_this_property_assignments_;
  }
  Handle<FixedArray> this_property_assignments() {
    return this_property_assignments_;
  }

  void AddProperty() { expected_property_count_++; }
  int expected_property_count() { return expected_property_count_; }
 private:
  // Captures the number of literals that need materialization in the
  // function.  Includes regexp literals, and boilerplate for object
  // and array literals.
  int materialized_literal_count_;

  // Properties count estimation.
  int expected_property_count_;

  bool only_this_property_assignments_;
  bool only_simple_this_property_assignments_;
  Handle<FixedArray> this_property_assignments_;

  // Bookkeeping
  Parser* parser_;
  TemporaryScope* parent_;

  friend class Parser;
};


TemporaryScope::TemporaryScope(Parser* parser)
  : materialized_literal_count_(0),
    expected_property_count_(0),
    only_this_property_assignments_(false),
    only_simple_this_property_assignments_(false),
    this_property_assignments_(Factory::empty_fixed_array()),
    parser_(parser),
    parent_(parser->temp_scope_) {
  parser->temp_scope_ = this;
}


TemporaryScope::~TemporaryScope() {
  parser_->temp_scope_ = parent_;
}


// A zone list wrapper lets code either access a access a zone list
// or appear to do so while actually ignoring all operations.
template <typename T>
class ZoneListWrapper {
 public:
  ZoneListWrapper() : list_(NULL) { }
  explicit ZoneListWrapper(int size) : list_(new ZoneList<T*>(size)) { }
  void Add(T* that) { if (list_) list_->Add(that); }
  int length() { return list_->length(); }
  ZoneList<T*>* elements() { return list_; }
  T* at(int index) { return list_->at(index); }
 private:
  ZoneList<T*>* list_;
};


// Allocation macro that should be used to allocate objects that must
// only be allocated in real parsing mode.  Note that in preparse mode
// not only is the syntax tree not created but the constructor
// arguments are not evaluated.
#define NEW(expr) (is_pre_parsing_ ? NULL : new expr)


class ParserFactory BASE_EMBEDDED {
 public:
  explicit ParserFactory(bool is_pre_parsing) :
      is_pre_parsing_(is_pre_parsing) { }

  virtual ~ParserFactory() { }

  virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);

  virtual Handle<String> LookupSymbol(const char* string, int length) {
    return Handle<String>();
  }

  virtual Handle<String> EmptySymbol() {
    return Handle<String>();
  }

  virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) {
    if (obj == VariableProxySentinel::this_proxy()) {
      return Property::this_property();
    } else {
      return ValidLeftHandSideSentinel::instance();
    }
  }

  virtual Expression* NewCall(Expression* expression,
                              ZoneList<Expression*>* arguments,
                              int pos) {
    return Call::sentinel();
  }

  virtual Statement* EmptyStatement() {
    return NULL;
  }

  template <typename T> ZoneListWrapper<T> NewList(int size) {
    return is_pre_parsing_ ? ZoneListWrapper<T>() : ZoneListWrapper<T>(size);
  }

 private:
  bool is_pre_parsing_;
};


class ParserLog BASE_EMBEDDED {
 public:
  virtual ~ParserLog() { }

  // Records the occurrence of a function.  The returned object is
  // only guaranteed to be valid until the next function has been
  // logged.
  virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); }

  virtual void LogError() { }
};


class AstBuildingParserFactory : public ParserFactory {
 public:
  AstBuildingParserFactory() : ParserFactory(false) { }

  virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);

  virtual Handle<String> LookupSymbol(const char* string, int length) {
    return Factory::LookupSymbol(Vector<const char>(string, length));
  }

  virtual Handle<String> EmptySymbol() {
    return Factory::empty_symbol();
  }

  virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) {
    return new Property(obj, key, pos);
  }

  virtual Expression* NewCall(Expression* expression,
                              ZoneList<Expression*>* arguments,
                              int pos) {
    return new Call(expression, arguments, pos);
  }

  virtual Statement* EmptyStatement();
};


class ParserRecorder: public ParserLog {
 public:
  ParserRecorder();
  virtual FunctionEntry LogFunction(int start);
  virtual void LogError() { }
  virtual void LogMessage(Scanner::Location loc,
                          const char* message,
                          Vector<const char*> args);
  void WriteString(Vector<const char> str);
  static const char* ReadString(unsigned* start, int* chars);
  List<unsigned>* store() { return &store_; }
 private:
  bool has_error_;
  List<unsigned> store_;
};


FunctionEntry ScriptDataImpl::GetFunctionEnd(int start) {
  if (nth(last_entry_).start_pos() > start) {
    // If the last entry we looked up is higher than what we're
    // looking for then it's useless and we reset it.
    last_entry_ = 0;
  }
  for (int i = last_entry_; i < EntryCount(); i++) {
    FunctionEntry entry = nth(i);
    if (entry.start_pos() == start) {
      last_entry_ = i;
      return entry;
    }
  }
  return FunctionEntry();
}


bool ScriptDataImpl::SanityCheck() {
  if (store_.length() < static_cast<int>(ScriptDataImpl::kHeaderSize))
    return false;
  if (magic() != ScriptDataImpl::kMagicNumber)
    return false;
  if (version() != ScriptDataImpl::kCurrentVersion)
    return false;
  return true;
}


int ScriptDataImpl::EntryCount() {
  return (store_.length() - kHeaderSize) / FunctionEntry::kSize;
}


FunctionEntry ScriptDataImpl::nth(int n) {
  int offset = kHeaderSize + n * FunctionEntry::kSize;
  return FunctionEntry(Vector<unsigned>(store_.start() + offset,
                                        FunctionEntry::kSize));
}


ParserRecorder::ParserRecorder()
  : has_error_(false), store_(4) {
  Vector<unsigned> preamble = store()->AddBlock(0, ScriptDataImpl::kHeaderSize);
  preamble[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
  preamble[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
  preamble[ScriptDataImpl::kHasErrorOffset] = false;
}


void ParserRecorder::WriteString(Vector<const char> str) {
  store()->Add(str.length());
  for (int i = 0; i < str.length(); i++)
    store()->Add(str[i]);
}


const char* ParserRecorder::ReadString(unsigned* start, int* chars) {
  int length = start[0];
  char* result = NewArray<char>(length + 1);
  for (int i = 0; i < length; i++)
    result[i] = start[i + 1];
  result[length] = '\0';
  if (chars != NULL) *chars = length;
  return result;
}


void ParserRecorder::LogMessage(Scanner::Location loc, const char* message,
                                Vector<const char*> args) {
  if (has_error_) return;
  store()->Rewind(ScriptDataImpl::kHeaderSize);
  store()->at(ScriptDataImpl::kHasErrorOffset) = true;
  store()->Add(loc.beg_pos);
  store()->Add(loc.end_pos);
  store()->Add(args.length());
  WriteString(CStrVector(message));
  for (int i = 0; i < args.length(); i++)
    WriteString(CStrVector(args[i]));
}


Scanner::Location ScriptDataImpl::MessageLocation() {
  int beg_pos = Read(0);
  int end_pos = Read(1);
  return Scanner::Location(beg_pos, end_pos);
}


const char* ScriptDataImpl::BuildMessage() {
  unsigned* start = ReadAddress(3);
  return ParserRecorder::ReadString(start, NULL);
}


Vector<const char*> ScriptDataImpl::BuildArgs() {
  int arg_count = Read(2);
  const char** array = NewArray<const char*>(arg_count);
  int pos = ScriptDataImpl::kHeaderSize + Read(3);
  for (int i = 0; i < arg_count; i++) {
    int count = 0;
    array[i] = ParserRecorder::ReadString(ReadAddress(pos), &count);
    pos += count + 1;
  }
  return Vector<const char*>(array, arg_count);
}


unsigned ScriptDataImpl::Read(int position) {
  return store_[ScriptDataImpl::kHeaderSize + position];
}


unsigned* ScriptDataImpl::ReadAddress(int position) {
  return &store_[ScriptDataImpl::kHeaderSize + position];
}


FunctionEntry ParserRecorder::LogFunction(int start) {
  if (has_error_) return FunctionEntry();
  FunctionEntry result(store()->AddBlock(0, FunctionEntry::kSize));
  result.set_start_pos(start);
  return result;
}


class AstBuildingParser : public Parser {
 public:
  AstBuildingParser(Handle<Script> script, bool allow_natives_syntax,
                    v8::Extension* extension, ScriptDataImpl* pre_data)
      : Parser(script, allow_natives_syntax, extension, false,
               factory(), log(), pre_data) { }
  virtual void ReportMessageAt(Scanner::Location loc, const char* message,
                               Vector<const char*> args);
  virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
                                 FunctionLiteral* fun, bool resolve, bool* ok);
  AstBuildingParserFactory* factory() { return &factory_; }
  ParserLog* log() { return &log_; }

 private:
  ParserLog log_;
  AstBuildingParserFactory factory_;
};


class PreParser : public Parser {
 public:
  PreParser(Handle<Script> script, bool allow_natives_syntax,
            v8::Extension* extension)
      : Parser(script, allow_natives_syntax, extension, true,
               factory(), recorder(), NULL)
      , factory_(true) { }
  virtual void ReportMessageAt(Scanner::Location loc, const char* message,
                               Vector<const char*> args);
  virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
                                 FunctionLiteral* fun, bool resolve, bool* ok);
  ParserFactory* factory() { return &factory_; }
  ParserRecorder* recorder() { return &recorder_; }

 private:
  ParserRecorder recorder_;
  ParserFactory factory_;
};


Scope* AstBuildingParserFactory::NewScope(Scope* parent, Scope::Type type,
                                          bool inside_with) {
  Scope* result = new Scope(parent, type);
  result->Initialize(inside_with);
  return result;
}


Statement* AstBuildingParserFactory::EmptyStatement() {
  // Use a statically allocated empty statement singleton to avoid
  // allocating lots and lots of empty statements.
  static v8::internal::EmptyStatement empty;
  return &empty;
}


Scope* ParserFactory::NewScope(Scope* parent, Scope::Type type,
                               bool inside_with) {
  ASSERT(parent != NULL);
  parent->type_ = type;
  return parent;
}


VariableProxy* PreParser::Declare(Handle<String> name, Variable::Mode mode,
                                  FunctionLiteral* fun, bool resolve,
                                  bool* ok) {
  return NULL;
}



// ----------------------------------------------------------------------------
// 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(Parser* parser, AstNode* node)
      : parser_(parser), node_(node), previous_(parser_->target_stack_) {
    parser_->target_stack_ = this;
  }

  ~Target() {
    parser_->target_stack_ = previous_;
  }

  Target* previous() { return previous_; }
  AstNode* node() { return node_; }

 private:
  Parser* parser_;
  AstNode* node_;
  Target* previous_;
};


class TargetScope BASE_EMBEDDED {
 public:
  explicit TargetScope(Parser* parser)
      : parser_(parser), previous_(parser->target_stack_) {
    parser->target_stack_ = NULL;
  }

  ~TargetScope() {
    parser_->target_stack_ = previous_;
  }

 private:
  Parser* parser_;
  Target* previous_;
};


// ----------------------------------------------------------------------------
// LexicalScope is a support class to facilitate manipulation of the
// Parser's scope stack. The constructor sets the parser's top scope
// to the incoming scope, and the destructor resets it.

class LexicalScope BASE_EMBEDDED {
 public:
  LexicalScope(Parser* parser, Scope* scope)
    : parser_(parser),
      prev_scope_(parser->top_scope_),
      prev_level_(parser->with_nesting_level_) {
    parser_->top_scope_ = scope;
    parser_->with_nesting_level_ = 0;
  }

  ~LexicalScope() {
    parser_->top_scope_ = prev_scope_;
    parser_->with_nesting_level_ = prev_level_;
  }

 private:
  Parser* parser_;
  Scope* prev_scope_;
  int prev_level_;
};


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

Parser::Parser(Handle<Script> script,
               bool allow_natives_syntax,
               v8::Extension* extension,
               bool is_pre_parsing,
               ParserFactory* factory,
               ParserLog* log,
               ScriptDataImpl* pre_data)
    : script_(script),
      scanner_(is_pre_parsing),
      top_scope_(NULL),
      with_nesting_level_(0),
      temp_scope_(NULL),
      target_stack_(NULL),
      allow_natives_syntax_(allow_natives_syntax),
      extension_(extension),
      factory_(factory),
      log_(log),
      is_pre_parsing_(is_pre_parsing),
      pre_data_(pre_data) {
}


bool Parser::PreParseProgram(Handle<String> source,
                             unibrow::CharacterStream* stream) {
  HistogramTimerScope timer(&Counters::pre_parse);
  AssertNoZoneAllocation assert_no_zone_allocation;
  AssertNoAllocation assert_no_allocation;
  NoHandleAllocation no_handle_allocation;
  scanner_.Init(source, stream, 0);
  ASSERT(target_stack_ == NULL);
  mode_ = PARSE_EAGERLY;
  DummyScope top_scope;
  LexicalScope scope(this, &top_scope);
  TemporaryScope temp_scope(this);
  ZoneListWrapper<Statement> processor;
  bool ok = true;
  ParseSourceElements(&processor, Token::EOS, &ok);
  return !scanner().stack_overflow();
}


FunctionLiteral* Parser::ParseProgram(Handle<String> source,
                                      unibrow::CharacterStream* stream,
                                      bool in_global_context) {
  CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);

  HistogramTimerScope timer(&Counters::parse);
  Counters::total_parse_size.Increment(source->length());

  // Initialize parser state.
  source->TryFlattenIfNotFlat();
  scanner_.Init(source, stream, 0);
  ASSERT(target_stack_ == NULL);

  // Compute the parsing mode.
  mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
  if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;

  Scope::Type type =
    in_global_context
      ? Scope::GLOBAL_SCOPE
      : Scope::EVAL_SCOPE;
  Handle<String> no_name = factory()->EmptySymbol();

  FunctionLiteral* result = NULL;
  { Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
    LexicalScope lexical_scope(this, scope);
    TemporaryScope temp_scope(this);
    ZoneListWrapper<Statement> body(16);
    bool ok = true;
    ParseSourceElements(&body, Token::EOS, &ok);
    if (ok) {
      result = NEW(FunctionLiteral(
          no_name,
          top_scope_,
          body.elements(),
          temp_scope.materialized_literal_count(),
          temp_scope.expected_property_count(),
          temp_scope.only_this_property_assignments(),
          temp_scope.only_simple_this_property_assignments(),
          temp_scope.this_property_assignments(),
          0,
          0,
          source->length(),
          false));
    } else if (scanner().stack_overflow()) {
      Top::StackOverflow();
    }
  }

  // Make sure the target stack is empty.
  ASSERT(target_stack_ == NULL);

  // If there was a syntax error we have to get rid of the AST
  // and it is not safe to do so before the scope has been deleted.
  if (result == NULL) zone_scope.DeleteOnExit();
  return result;
}


FunctionLiteral* Parser::ParseLazy(Handle<String> source,
                                   Handle<String> name,
                                   int start_position,
                                   bool is_expression) {
  CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
  HistogramTimerScope timer(&Counters::parse_lazy);
  source->TryFlattenIfNotFlat();
  Counters::total_parse_size.Increment(source->length());
  SafeStringInputBuffer buffer(source.location());

  // Initialize parser state.
  scanner_.Init(source, &buffer, start_position);
  ASSERT(target_stack_ == NULL);
  mode_ = PARSE_EAGERLY;

  // Place holder for the result.
  FunctionLiteral* result = NULL;

  {
    // Parse the function literal.
    Handle<String> no_name = factory()->EmptySymbol();
    Scope* scope =
        factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
    LexicalScope lexical_scope(this, scope);
    TemporaryScope temp_scope(this);

    FunctionLiteralType type = is_expression ? EXPRESSION : DECLARATION;
    bool ok = true;
    result = ParseFunctionLiteral(name, RelocInfo::kNoPosition, type, &ok);
    // Make sure the results agree.
    ASSERT(ok == (result != NULL));
    // The only errors should be stack overflows.
    ASSERT(ok || scanner_.stack_overflow());
  }

  // Make sure the target stack is empty.
  ASSERT(target_stack_ == NULL);

  // If there was a stack overflow we have to get rid of AST and it is
  // not safe to do before scope has been deleted.
  if (result == NULL) {
    Top::StackOverflow();
    zone_scope.DeleteOnExit();
  }
  return result;
}


void Parser::ReportMessage(const char* type, Vector<const char*> args) {
  Scanner::Location source_location = scanner_.location();
  ReportMessageAt(source_location, type, args);
}


void AstBuildingParser::ReportMessageAt(Scanner::Location source_location,
                                        const char* type,
                                        Vector<const char*> args) {
  MessageLocation location(script_,
                           source_location.beg_pos, source_location.end_pos);
  Handle<JSArray> array = Factory::NewJSArray(args.length());
  for (int i = 0; i < args.length(); i++) {
    SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i])));
  }
  Handle<Object> result = Factory::NewSyntaxError(type, array);
  Top::Throw(*result, &location);
}


void PreParser::ReportMessageAt(Scanner::Location source_location,
                                const char* type,
                                Vector<const char*> args) {
  recorder()->LogMessage(source_location, type, args);
}


// Base class containing common code for the different finder classes used by
// the parser.
class ParserFinder {
 protected:
  ParserFinder() {}
  static Assignment* AsAssignment(Statement* stat) {
    if (stat == NULL) return NULL;
    ExpressionStatement* exp_stat = stat->AsExpressionStatement();
    if (exp_stat == NULL) return NULL;
    return exp_stat->expression()->AsAssignment();
  }
};


// An InitializationBlockFinder finds and marks sequences of statements of the
// form x.y.z.a = ...; x.y.z.b = ...; etc.
class InitializationBlockFinder : public ParserFinder {
 public:
  InitializationBlockFinder()
    : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}

  ~InitializationBlockFinder() {
    if (InBlock()) EndBlock();
  }

  void Update(Statement* stat) {
    Assignment* assignment = AsAssignment(stat);
    if (InBlock()) {
      if (BlockContinues(assignment)) {
        UpdateBlock(assignment);
      } else {
        EndBlock();
      }
    }
    if (!InBlock() && (assignment != NULL) &&
        (assignment->op() == Token::ASSIGN)) {
      StartBlock(assignment);
    }
  }

 private:
  // Returns true if the expressions appear to denote the same object.
  // In the context of initialization blocks, we only consider expressions
  // of the form 'x.y.z'.
  static bool SameObject(Expression* e1, Expression* e2) {
    VariableProxy* v1 = e1->AsVariableProxy();
    VariableProxy* v2 = e2->AsVariableProxy();
    if (v1 != NULL && v2 != NULL) {
      return v1->name()->Equals(*v2->name());
    }
    Property* p1 = e1->AsProperty();
    Property* p2 = e2->AsProperty();
    if ((p1 == NULL) || (p2 == NULL)) return false;
    Literal* key1 = p1->key()->AsLiteral();
    Literal* key2 = p2->key()->AsLiteral();
    if ((key1 == NULL) || (key2 == NULL)) return false;
    if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
      return false;
    }
    String* name1 = String::cast(*key1->handle());
    String* name2 = String::cast(*key2->handle());
    if (!name1->Equals(name2)) return false;
    return SameObject(p1->obj(), p2->obj());
  }

  // Returns true if the expressions appear to denote different properties
  // of the same object.
  static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
    Property* p1 = e1->AsProperty();
    Property* p2 = e2->AsProperty();
    if ((p1 == NULL) || (p2 == NULL)) return false;
    return SameObject(p1->obj(), p2->obj());
  }

  bool BlockContinues(Assignment* assignment) {
    if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
    if (assignment->op() != Token::ASSIGN) return false;
    return PropertyOfSameObject(first_in_block_->target(),
                                assignment->target());
  }

  void StartBlock(Assignment* assignment) {
    first_in_block_ = assignment;
    last_in_block_ = assignment;
    block_size_ = 1;
  }

  void UpdateBlock(Assignment* assignment) {
    last_in_block_ = assignment;
    ++block_size_;
  }

  void EndBlock() {
    if (block_size_ >= Parser::kMinInitializationBlock) {
      first_in_block_->mark_block_start();
      last_in_block_->mark_block_end();
    }
    last_in_block_ = first_in_block_ = NULL;
    block_size_ = 0;
  }

  bool InBlock() { return first_in_block_ != NULL; }

  Assignment* first_in_block_;
  Assignment* last_in_block_;
  int block_size_;

  DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
};


// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
// this.x = ...;, where x is a named property. It also determines whether a
// function contains only assignments of this type.
class ThisNamedPropertyAssigmentFinder : public ParserFinder {
 public:
  ThisNamedPropertyAssigmentFinder()
      : only_this_property_assignments_(true),
        only_simple_this_property_assignments_(true),
        names_(NULL),
        assigned_arguments_(NULL),
        assigned_constants_(NULL) {}

  void Update(Scope* scope, Statement* stat) {
    // Bail out if function already has non this property assignment
    // statements.
    if (!only_this_property_assignments_) {
      return;
    }

    // Check whether this statement is of the form this.x = ...;
    Assignment* assignment = AsAssignment(stat);
    if (IsThisPropertyAssignment(assignment)) {
      HandleThisPropertyAssignment(scope, assignment);
    } else {
      only_this_property_assignments_ = false;
      only_simple_this_property_assignments_ = false;
    }
  }

  // Returns whether only statements of the form this.x = ...; was encountered.
  bool only_this_property_assignments() {
    return only_this_property_assignments_;
  }

  // Returns whether only statements of the form this.x = y; where y is either a
  // constant or a function argument was encountered.
  bool only_simple_this_property_assignments() {
    return only_simple_this_property_assignments_;
  }

  // Returns a fixed array containing three elements for each assignment of the
  // form this.x = y;
  Handle<FixedArray> GetThisPropertyAssignments() {
    if (names_ == NULL) {
      return Factory::empty_fixed_array();
    }
    ASSERT(names_ != NULL);
    ASSERT(assigned_arguments_ != NULL);
    ASSERT_EQ(names_->length(), assigned_arguments_->length());
    ASSERT_EQ(names_->length(), assigned_constants_->length());
    Handle<FixedArray> assignments =
        Factory::NewFixedArray(names_->length() * 3);
    for (int i = 0; i < names_->length(); i++) {
      assignments->set(i * 3, *names_->at(i));
      assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
      assignments->set(i * 3 + 2, *assigned_constants_->at(i));
    }
    return assignments;
  }

 private:
  bool IsThisPropertyAssignment(Assignment* assignment) {
    if (assignment != NULL) {
      Property* property = assignment->target()->AsProperty();
      return assignment->op() == Token::ASSIGN
             && property != NULL
             && property->obj()->AsVariableProxy() != NULL
             && property->obj()->AsVariableProxy()->is_this();
    }
    return false;
  }

  void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
    // Check that the property assigned to is a named property.
    Property* property = assignment->target()->AsProperty();
    ASSERT(property != NULL);
    Literal* literal = property->key()->AsLiteral();
    uint32_t dummy;
    if (literal != NULL &&
        literal->handle()->IsString() &&
        !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
      Handle<String> key = Handle<String>::cast(literal->handle());

      // Check whether the value assigned is either a constant or matches the
      // name of one of the arguments to the function.
      if (assignment->value()->AsLiteral() != NULL) {
        // Constant assigned.
        Literal* literal = assignment->value()->AsLiteral();
        AssignmentFromConstant(key, literal->handle());
      } else if (assignment->value()->AsVariableProxy() != NULL) {
        // Variable assigned.
        Handle<String> name =
            assignment->value()->AsVariableProxy()->name();
        // Check whether the variable assigned matches an argument name.
        int index = -1;
        for (int i = 0; i < scope->num_parameters(); i++) {
          if (*scope->parameter(i)->name() == *name) {
            // Assigned from function argument.
            index = i;
            break;
          }
        }
        if (index != -1) {
          AssignmentFromParameter(key, index);
        } else {
          AssignmentFromSomethingElse(key);
        }
      } else {
        AssignmentFromSomethingElse(key);
      }
    }
  }

  void AssignmentFromParameter(Handle<String> name, int index) {
    EnsureAllocation();
    names_->Add(name);
    assigned_arguments_->Add(index);
    assigned_constants_->Add(Factory::undefined_value());
  }

  void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
    EnsureAllocation();
    names_->Add(name);
    assigned_arguments_->Add(-1);
    assigned_constants_->Add(value);
  }

  void AssignmentFromSomethingElse(Handle<String> name) {
    EnsureAllocation();
    names_->Add(name);
    assigned_arguments_->Add(-1);
    assigned_constants_->Add(Factory::undefined_value());

    // The this assignment is not a simple one.
    only_simple_this_property_assignments_ = false;
  }

  void EnsureAllocation() {
    if (names_ == NULL) {
      ASSERT(assigned_arguments_ == NULL);
      ASSERT(assigned_constants_ == NULL);
      names_ = new ZoneStringList(4);
      assigned_arguments_ = new ZoneList<int>(4);
      assigned_constants_ = new ZoneObjectList(4);
    }
  }

  bool only_this_property_assignments_;
  bool only_simple_this_property_assignments_;
  ZoneStringList* names_;
  ZoneList<int>* assigned_arguments_;
  ZoneObjectList* assigned_constants_;
};


void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,
                                  int end_token,
                                  bool* ok) {
  // SourceElements ::
  //   (Statement)* <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);

  ASSERT(processor != NULL);
  InitializationBlockFinder block_finder;
  ThisNamedPropertyAssigmentFinder this_property_assignment_finder;
  while (peek() != end_token) {
    Statement* stat = ParseStatement(NULL, CHECK_OK);
    if (stat == NULL || stat->IsEmpty()) continue;
    // We find and mark the initialization blocks on top level code only.
    // This is because the optimization prevents reuse of the map transitions,
    // so it should be used only for code that will only be run once.
    if (top_scope_->is_global_scope()) {
      block_finder.Update(stat);
    }
    // Find and mark all assignments to named properties in this (this.x =)
    if (top_scope_->is_function_scope()) {
      this_property_assignment_finder.Update(top_scope_, stat);
    }
    processor->Add(stat);
  }

  // Propagate the collected information on this property assignments.
  if (top_scope_->is_function_scope()) {
    if (this_property_assignment_finder.only_this_property_assignments()) {
      temp_scope_->SetThisPropertyAssignmentInfo(
          this_property_assignment_finder.only_this_property_assignments(),
          this_property_assignment_finder.
              only_simple_this_property_assignments(),
          this_property_assignment_finder.GetThisPropertyAssignments());
    }
  }
  return 0;
}


Statement* Parser::ParseStatement(ZoneStringList* 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.

  // Keep the source position of the statement
  int statement_pos = scanner().peek_location().beg_pos;
  Statement* stmt = NULL;
  switch (peek()) {
    case Token::LBRACE:
      return ParseBlock(labels, ok);

    case Token::CONST:  // fall through
    case Token::VAR:
      stmt = ParseVariableStatement(ok);
      break;

    case Token::SEMICOLON:
      Next();
      return factory()->EmptyStatement();

    case Token::IF:
      stmt = ParseIfStatement(labels, ok);
      break;

    case Token::DO:
      stmt = ParseDoWhileStatement(labels, ok);
      break;

    case Token::WHILE:
      stmt = ParseWhileStatement(labels, ok);
      break;

    case Token::FOR:
      stmt = ParseForStatement(labels, ok);
      break;

    case Token::CONTINUE:
      stmt = ParseContinueStatement(ok);
      break;

    case Token::BREAK:
      stmt = ParseBreakStatement(labels, ok);
      break;

    case Token::RETURN:
      stmt = ParseReturnStatement(ok);
      break;

    case Token::WITH:
      stmt = ParseWithStatement(labels, ok);
      break;

    case Token::SWITCH:
      stmt = ParseSwitchStatement(labels, ok);
      break;

    case Token::THROW:
      stmt = ParseThrowStatement(ok);
      break;

    case Token::TRY: {
      // NOTE: It is somewhat complicated to have labels on
      // try-statements. When breaking out of a try-finally statement,
      // one must take great care not to treat it as a
      // fall-through. It is much easier just to wrap the entire
      // try-statement in a statement block and put the labels there
      Block* result = NEW(Block(labels, 1, false));
      Target target(this, result);
      TryStatement* statement = ParseTryStatement(CHECK_OK);
      if (statement) {
        statement->set_statement_pos(statement_pos);
      }
      if (result) result->AddStatement(statement);
      return result;
    }

    case Token::FUNCTION:
      return ParseFunctionDeclaration(ok);

    case Token::NATIVE:
      return ParseNativeDeclaration(ok);

    case Token::DEBUGGER:
      stmt = ParseDebuggerStatement(ok);
      break;

    default:
      stmt = ParseExpressionOrLabelledStatement(labels, ok);
  }

  // Store the source position of the statement
  if (stmt != NULL) stmt->set_statement_pos(statement_pos);
  return stmt;
}


VariableProxy* AstBuildingParser::Declare(Handle<String> name,
                                          Variable::Mode mode,
                                          FunctionLiteral* fun,
                                          bool resolve,
                                          bool* ok) {
  Variable* var = NULL;
  // If we are inside a function, a declaration of a variable
  // is a truly local variable, and the scope of the variable
  // is always the function scope.

  // If a function 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 declarations inside an eval scope need to be added
  // to the calling function context.
  if (top_scope_->is_function_scope()) {
    // Declare the variable in the function scope.
    var = top_scope_->LocalLookup(name);
    if (var == NULL) {
      // Declare the name.
      var = top_scope_->DeclareLocal(name, mode);
    } else {
      // The name was declared before; check for conflicting
      // re-declarations. If the previous declaration was a const or the
      // current declaration is a const then we have a conflict. There is
      // similar code in runtime.cc in the Declare functions.
      if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
        // We only have vars and consts in declarations.
        ASSERT(var->mode() == Variable::VAR ||
               var->mode() == Variable::CONST);
        const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
        Handle<String> type_string =
            Factory::NewStringFromUtf8(CStrVector(type), TENURED);
        Expression* expression =
            NewThrowTypeError(Factory::redeclaration_symbol(),
                              type_string, name);
        top_scope_->SetIllegalRedeclaration(expression);
      }
    }
  }

  // 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
  // Runtime::DeclareContextSlot() calls.
  VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
  top_scope_->AddDeclaration(NEW(Declaration(proxy, mode, fun)));

  // For global const variables we bind the proxy to a variable.
  if (mode == Variable::CONST && top_scope_->is_global_scope()) {
    ASSERT(resolve);  // should be set by all callers
    Variable::Kind kind = Variable::NORMAL;
    var = NEW(Variable(top_scope_, name, Variable::CONST, true, kind));
  }

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


// 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) {
  if (extension_ == NULL) {
    ReportUnexpectedToken(Token::NATIVE);
    *ok = false;
    return NULL;
  }

  Expect(Token::NATIVE, CHECK_OK);
  Expect(Token::FUNCTION, CHECK_OK);
  Handle<String> name = ParseIdentifier(CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  bool done = (peek() == Token::RPAREN);
  while (!done) {
    ParseIdentifier(CHECK_OK);
    done = (peek() == Token::RPAREN);
    if (!done) Expect(Token::COMMA, CHECK_OK);
  }
  Expect(Token::RPAREN, CHECK_OK);
  Expect(Token::SEMICOLON, CHECK_OK);

  if (is_pre_parsing_) return NULL;

  // 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.
  top_scope_->ForceEagerCompilation();

  // Compute the function template for the native function.
  v8::Handle<v8::FunctionTemplate> fun_template =
      extension_->GetNativeFunction(v8::Utils::ToLocal(name));
  ASSERT(!fun_template.IsEmpty());

  // Instantiate the function and create a boilerplate function from it.
  Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
  const int literals = fun->NumberOfLiterals();
  Handle<Code> code = Handle<Code>(fun->shared()->code());
  Handle<JSFunction> boilerplate =
      Factory::NewFunctionBoilerplate(name, literals, code);

  // Copy the function data to the boilerplate. Used by
  // builtins.cc:HandleApiCall to perform argument type checks and to
  // find the right native code to call.
  boilerplate->shared()->set_function_data(fun->shared()->function_data());
  int parameters = fun->shared()->formal_parameter_count();
  boilerplate->shared()->set_formal_parameter_count(parameters);

  // TODO(1240846): It's weird that native function declarations are
  // introduced dynamically when we meet their declarations, whereas
  // other functions are setup when entering the surrounding scope.
  FunctionBoilerplateLiteral* lit =
      NEW(FunctionBoilerplateLiteral(boilerplate));
  VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
  return NEW(ExpressionStatement(
      new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)));
}


Statement* Parser::ParseFunctionDeclaration(bool* ok) {
  // FunctionDeclaration ::
  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
  Expect(Token::FUNCTION, CHECK_OK);
  int function_token_position = scanner().location().beg_pos;
  Handle<String> name = ParseIdentifier(CHECK_OK);
  FunctionLiteral* fun = ParseFunctionLiteral(name,
                                              function_token_position,
                                              DECLARATION,
                                              CHECK_OK);
  // Even if we're not at the top-level of the global or a function
  // scope, we treat is as such and introduce the function with it's
  // initial value upon entering the corresponding scope.
  Declare(name, Variable::VAR, fun, true, CHECK_OK);
  return factory()->EmptyStatement();
}


Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
  // Block ::
  //   '{' Statement* '}'

  // Note that a Block does not introduce a new execution scope!
  // (ECMA-262, 3rd, 12.2)
  //
  // Construct block expecting 16 statements.
  Block* result = NEW(Block(labels, 16, false));
  Target target(this, result);
  Expect(Token::LBRACE, CHECK_OK);
  while (peek() != Token::RBRACE) {
    Statement* stat = ParseStatement(NULL, CHECK_OK);
    if (stat && !stat->IsEmpty()) result->AddStatement(stat);
  }
  Expect(Token::RBRACE, CHECK_OK);
  return result;
}


Block* Parser::ParseVariableStatement(bool* ok) {
  // VariableStatement ::
  //   VariableDeclarations ';'

  Expression* dummy;  // to satisfy the ParseVariableDeclarations() signature
  Block* result = ParseVariableDeclarations(true, &dummy, 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 used for the parsing
// of 'for-in' loops.
Block* Parser::ParseVariableDeclarations(bool accept_IN,
                                         Expression** var,
                                         bool* ok) {
  // VariableDeclarations ::
  //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']

  Variable::Mode mode = Variable::VAR;
  bool is_const = false;
  if (peek() == Token::VAR) {
    Consume(Token::VAR);
  } else if (peek() == Token::CONST) {
    Consume(Token::CONST);
    mode = Variable::CONST;
    is_const = true;
  } else {
    UNREACHABLE();  // by current callers
  }

  // The scope of a variable/const declared anywhere inside a function
  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
  // transform a source-level variable/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.
  //
  // Create new block with one expected declaration.
  Block* block = NEW(Block(NULL, 1, true));
  VariableProxy* last_var = NULL;  // the last variable declared
  int nvars = 0;  // the number of variables declared
  do {
    // Parse variable name.
    if (nvars > 0) Consume(Token::COMMA);
    Handle<String> name = ParseIdentifier(CHECK_OK);

    // 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 const declaration, in an inner scope, the proxy is always
    // bound to the declared variable (independent of possibly surrounding with
    // statements).
    last_var = Declare(name, mode, NULL,
                       is_const /* always bound for CONST! */,
                       CHECK_OK);
    nvars++;

    // Parse initialization expression if present and/or 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' as it may be a
    // different 'v' than the 'v' in the declaration (if we are inside
    // a 'with' statement that makes a object property with name 'v'
    // visible).
    //
    // 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).

    Expression* value = NULL;
    int position = -1;
    if (peek() == Token::ASSIGN) {
      Expect(Token::ASSIGN, CHECK_OK);
      position = scanner().location().beg_pos;
      value = ParseAssignmentExpression(accept_IN, CHECK_OK);
    }

    // Make sure that 'const c' actually initializes 'c' to undefined
    // even though it seems like a stupid thing to do.
    if (value == NULL && is_const) {
      value = GetLiteralUndefined();
    }

    // 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 (not even in a prototype of the global object) 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 a "local" variable; a
    // variable defined in the global object and not in any
    // prototype. 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 (!is_pre_parsing_ && top_scope_->is_global_scope()) {
      // Compute the arguments for the runtime call.
      ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
      // 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.
      arguments->Add(NEW(Literal(name)));  // we have at least 1 parameter
      if (is_const || (value != NULL && !inside_with())) {
        arguments->Add(value);
        value = NULL;  // zap the value to avoid the unnecessary assignment
      }
      // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
      // and add it to the initialization statement block. Note that
      // this function does different things depending on if we have
      // 1 or 2 parameters.
      CallRuntime* initialize;
      if (is_const) {
        initialize =
          NEW(CallRuntime(
            Factory::InitializeConstGlobal_symbol(),
            Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
            arguments));
      } else {
        initialize =
          NEW(CallRuntime(
            Factory::InitializeVarGlobal_symbol(),
            Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
            arguments));
      }
      block->AddStatement(NEW(ExpressionStatement(initialize)));
    }

    // Add an assignment node to the initialization statement block if
    // we still have a pending initialization value. We must distinguish
    // between variables and constants: Variable initializations are simply
    // assignments (with all the consequences if they are inside a 'with'
    // statement - they may change a 'with' object property). 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 variables). Sigh...
    if (value != NULL) {
      Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
      Assignment* assignment = NEW(Assignment(op, last_var, value, position));
      if (block) block->AddStatement(NEW(ExpressionStatement(assignment)));
    }
  } while (peek() == Token::COMMA);

  if (!is_const && nvars == 1) {
    // We have a single, non-const variable.
    if (is_pre_parsing_) {
      // If we're preparsing then we need to set the var to something
      // in order for for-in loops to parse correctly.
      *var = ValidLeftHandSideSentinel::instance();
    } else {
      ASSERT(last_var != NULL);
      *var = last_var;
    }
  }

  return block;
}


static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
  ASSERT(!label.is_null());
  if (labels != NULL)
    for (int i = labels->length(); i-- > 0; )
      if (labels->at(i).is_identical_to(label))
        return true;

  return false;
}


Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
                                                      bool* ok) {
  // ExpressionStatement | LabelledStatement ::
  //   Expression ';'
  //   Identifier ':' Statement

  Expression* expr = ParseExpression(true, CHECK_OK);
  if (peek() == Token::COLON && expr &&
      expr->AsVariableProxy() != NULL &&
      !expr->AsVariableProxy()->is_this()) {
    VariableProxy* var = expr->AsVariableProxy();
    Handle<String> label = var->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 (!is_pre_parsing_) {
      if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
        SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
        const char* elms[2] = { "Label", *c_string };
        Vector<const char*> args(elms, 2);
        ReportMessage("redeclaration", args);
        *ok = false;
        return NULL;
      }
      if (labels == NULL) labels = new ZoneStringList(4);
      labels->Add(label);
      // 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.
      top_scope_->RemoveUnresolved(var);
    }
    Expect(Token::COLON, CHECK_OK);
    return ParseStatement(labels, ok);
  }

  // Parsed expression statement.
  ExpectSemicolon(CHECK_OK);
  return NEW(ExpressionStatement(expr));
}


IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
  // IfStatement ::
  //   'if' '(' Expression ')' Statement ('else' Statement)?

  Expect(Token::IF, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  Expression* condition = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);
  Statement* then_statement = ParseStatement(labels, CHECK_OK);
  Statement* else_statement = NULL;
  if (peek() == Token::ELSE) {
    Next();
    else_statement = ParseStatement(labels, CHECK_OK);
  } else if (!is_pre_parsing_) {
    else_statement = factory()->EmptyStatement();
  }
  return NEW(IfStatement(condition, then_statement, else_statement));
}


Statement* Parser::ParseContinueStatement(bool* ok) {
  // ContinueStatement ::
  //   'continue' Identifier? ';'

  Expect(Token::CONTINUE, CHECK_OK);
  Handle<String> label = Handle<String>::null();
  Token::Value tok = peek();
  if (!scanner_.has_line_terminator_before_next() &&
      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
    label = ParseIdentifier(CHECK_OK);
  }
  IterationStatement* target = NULL;
  if (!is_pre_parsing_) {
    target = LookupContinueTarget(label, CHECK_OK);
    if (target == NULL) {
      // Illegal continue statement.  To be consistent with KJS we delay
      // reporting of the syntax error until runtime.
      Handle<String> error_type = Factory::illegal_continue_symbol();
      if (!label.is_null()) error_type = Factory::unknown_label_symbol();
      Expression* throw_error = NewThrowSyntaxError(error_type, label);
      return NEW(ExpressionStatement(throw_error));
    }
  }
  ExpectSemicolon(CHECK_OK);
  return NEW(ContinueStatement(target));
}


Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
  // BreakStatement ::
  //   'break' Identifier? ';'

  Expect(Token::BREAK, CHECK_OK);
  Handle<String> label;
  Token::Value tok = peek();
  if (!scanner_.has_line_terminator_before_next() &&
      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
    label = ParseIdentifier(CHECK_OK);
  }
  // Parse labeled break statements that target themselves into
  // empty statements, e.g. 'l1: l2: l3: break l2;'
  if (!label.is_null() && ContainsLabel(labels, label)) {
    return factory()->EmptyStatement();
  }
  BreakableStatement* target = NULL;
  if (!is_pre_parsing_) {
    target = LookupBreakTarget(label, CHECK_OK);
    if (target == NULL) {
      // Illegal break statement.  To be consistent with KJS we delay
      // reporting of the syntax error until runtime.
      Handle<String> error_type = Factory::illegal_break_symbol();
      if (!label.is_null()) error_type = Factory::unknown_label_symbol();
      Expression* throw_error = NewThrowSyntaxError(error_type, label);
      return NEW(ExpressionStatement(throw_error));
    }
  }
  ExpectSemicolon(CHECK_OK);
  return NEW(BreakStatement(target));
}


Statement* Parser::ParseReturnStatement(bool* ok) {
  // ReturnStatement ::
  //   'return' Expression? ';'

  // Consume the return token. It is necessary to do the before
  // reporting any errors on it, because of the way errors are
  // reported (underlining).
  Expect(Token::RETURN, CHECK_OK);

  // 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.
  //
  // To be consistent with KJS we report the syntax error at runtime.
  if (!is_pre_parsing_ && !top_scope_->is_function_scope()) {
    Handle<String> type = Factory::illegal_return_symbol();
    Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
    return NEW(ExpressionStatement(throw_error));
  }

  Token::Value tok = peek();
  if (scanner_.has_line_terminator_before_next() ||
      tok == Token::SEMICOLON ||
      tok == Token::RBRACE ||
      tok == Token::EOS) {
    ExpectSemicolon(CHECK_OK);
    return NEW(ReturnStatement(GetLiteralUndefined()));
  }

  Expression* expr = ParseExpression(true, CHECK_OK);
  ExpectSemicolon(CHECK_OK);
  return NEW(ReturnStatement(expr));
}


Block* Parser::WithHelper(Expression* obj,
                          ZoneStringList* labels,
                          bool is_catch_block,
                          bool* ok) {
  // Parse the statement and collect escaping labels.
  ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0));
  TargetCollector collector(target_list);
  Statement* stat;
  { Target target(this, &collector);
    with_nesting_level_++;
    top_scope_->RecordWithStatement();
    stat = ParseStatement(labels, CHECK_OK);
    with_nesting_level_--;
  }
  // Create resulting block with two statements.
  // 1: Evaluate the with expression.
  // 2: The try-finally block evaluating the body.
  Block* result = NEW(Block(NULL, 2, false));

  if (result != NULL) {
    result->AddStatement(NEW(WithEnterStatement(obj, is_catch_block)));

    // Create body block.
    Block* body = NEW(Block(NULL, 1, false));
    body->AddStatement(stat);

    // Create exit block.
    Block* exit = NEW(Block(NULL, 1, false));
    exit->AddStatement(NEW(WithExitStatement()));

    // Return a try-finally statement.
    TryFinallyStatement* wrapper = NEW(TryFinallyStatement(body, exit));
    wrapper->set_escaping_targets(collector.targets());
    result->AddStatement(wrapper);
  }
  return result;
}


Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
  // WithStatement ::
  //   'with' '(' Expression ')' Statement

  Expect(Token::WITH, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  Expression* expr = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);

  return WithHelper(expr, labels, false, CHECK_OK);
}


CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
  // CaseClause ::
  //   'case' Expression ':' Statement*
  //   'default' ':' Statement*

  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("multiple_defaults_in_switch",
                    Vector<const char*>::empty());
      *ok = false;
      return NULL;
    }
    *default_seen_ptr = true;
  }
  Expect(Token::COLON, CHECK_OK);

  ZoneListWrapper<Statement> statements = factory()->NewList<Statement>(5);
  while (peek() != Token::CASE &&
         peek() != Token::DEFAULT &&
         peek() != Token::RBRACE) {
    Statement* stat = ParseStatement(NULL, CHECK_OK);
    statements.Add(stat);
  }

  return NEW(CaseClause(label, statements.elements()));
}


SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
                                              bool* ok) {
  // SwitchStatement ::
  //   'switch' '(' Expression ')' '{' CaseClause* '}'

  SwitchStatement* statement = NEW(SwitchStatement(labels));
  Target target(this, statement);

  Expect(Token::SWITCH, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  Expression* tag = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);

  bool default_seen = false;
  ZoneListWrapper<CaseClause> cases = factory()->NewList<CaseClause>(4);
  Expect(Token::LBRACE, CHECK_OK);
  while (peek() != Token::RBRACE) {
    CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
    cases.Add(clause);
  }
  Expect(Token::RBRACE, CHECK_OK);

  if (statement) statement->Initialize(tag, cases.elements());
  return statement;
}


Statement* Parser::ParseThrowStatement(bool* ok) {
  // ThrowStatement ::
  //   'throw' Expression ';'

  Expect(Token::THROW, CHECK_OK);
  int pos = scanner().location().beg_pos;
  if (scanner_.has_line_terminator_before_next()) {
    ReportMessage("newline_after_throw", Vector<const char*>::empty());
    *ok = false;
    return NULL;
  }
  Expression* exception = ParseExpression(true, CHECK_OK);
  ExpectSemicolon(CHECK_OK);

  return NEW(ExpressionStatement(new Throw(exception, 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);

  ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0));
  TargetCollector collector(target_list);
  Block* try_block;

  { Target target(this, &collector);
    try_block = ParseBlock(NULL, CHECK_OK);
  }

  Block* catch_block = NULL;
  VariableProxy* catch_var = NULL;
  Block* finally_block = NULL;

  Token::Value tok = peek();
  if (tok != Token::CATCH && tok != Token::FINALLY) {
    ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
    *ok = false;
    return NULL;
  }

  // If we can break out from the catch block and there is a finally block,
  // then we will need to collect jump targets from the catch block. Since
  // we don't know yet if there will be a finally block, we always collect
  // the jump targets.
  ZoneList<BreakTarget*>* catch_target_list = NEW(ZoneList<BreakTarget*>(0));
  TargetCollector catch_collector(catch_target_list);
  bool has_catch = false;
  if (tok == Token::CATCH) {
    has_catch = true;
    Consume(Token::CATCH);

    Expect(Token::LPAREN, CHECK_OK);
    Handle<String> name = ParseIdentifier(CHECK_OK);
    Expect(Token::RPAREN, CHECK_OK);

    if (peek() == Token::LBRACE) {
      // Allocate a temporary for holding the finally state while
      // executing the finally block.
      catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
      Literal* name_literal = NEW(Literal(name));
      Expression* obj = NEW(CatchExtensionObject(name_literal, catch_var));
      { Target target(this, &catch_collector);
        catch_block = WithHelper(obj, NULL, true, CHECK_OK);
      }
    } else {
      Expect(Token::LBRACE, CHECK_OK);
    }

    tok = peek();
  }

  if (tok == Token::FINALLY || !has_catch) {
    Consume(Token::FINALLY);
    // Declare a variable for holding the finally state while
    // executing the finally block.
    finally_block = ParseBlock(NULL, CHECK_OK);
  }

  // Simplify the AST nodes by converting:
  //   'try { } catch { } finally { }'
  // to:
  //   'try { try { } catch { } } finally { }'

  if (!is_pre_parsing_ && catch_block != NULL && finally_block != NULL) {
    TryCatchStatement* statement =
        NEW(TryCatchStatement(try_block, catch_var, catch_block));
    statement->set_escaping_targets(collector.targets());
    try_block = NEW(Block(NULL, 1, false));
    try_block->AddStatement(statement);
    catch_block = NULL;
  }

  TryStatement* result = NULL;
  if (!is_pre_parsing_) {
    if (catch_block != NULL) {
      ASSERT(finally_block == NULL);
      result = NEW(TryCatchStatement(try_block, catch_var, catch_block));
      result->set_escaping_targets(collector.targets());
    } else {
      ASSERT(finally_block != NULL);
      result = NEW(TryFinallyStatement(try_block, finally_block));
      // Add the jump targets of the try block and the catch block.
      for (int i = 0; i < collector.targets()->length(); i++) {
        catch_collector.AddTarget(collector.targets()->at(i));
      }
      result->set_escaping_targets(catch_collector.targets());
    }
  }

  return result;
}


DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
                                                bool* ok) {
  // DoStatement ::
  //   'do' Statement 'while' '(' Expression ')' ';'

  DoWhileStatement* loop = NEW(DoWhileStatement(labels));
  Target target(this, loop);

  Expect(Token::DO, CHECK_OK);
  Statement* body = ParseStatement(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(ZoneStringList* labels, bool* ok) {
  // WhileStatement ::
  //   'while' '(' Expression ')' Statement

  WhileStatement* loop = NEW(WhileStatement(labels));
  Target target(this, loop);

  Expect(Token::WHILE, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  Expression* cond = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);
  Statement* body = ParseStatement(NULL, CHECK_OK);

  if (loop != NULL) loop->Initialize(cond, body);
  return loop;
}


Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
  // ForStatement ::
  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement

  Statement* init = NULL;

  Expect(Token::FOR, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  if (peek() != Token::SEMICOLON) {
    if (peek() == Token::VAR || peek() == Token::CONST) {
      Expression* each = NULL;
      Block* variable_statement =
          ParseVariableDeclarations(false, &each, CHECK_OK);
      if (peek() == Token::IN && each != NULL) {
        ForInStatement* loop = NEW(ForInStatement(labels));
        Target target(this, loop);

        Expect(Token::IN, CHECK_OK);
        Expression* enumerable = ParseExpression(true, CHECK_OK);
        Expect(Token::RPAREN, CHECK_OK);

        Statement* body = ParseStatement(NULL, CHECK_OK);
        if (is_pre_parsing_) {
          return NULL;
        } else {
          loop->Initialize(each, enumerable, body);
          Block* result = NEW(Block(NULL, 2, false));
          result->AddStatement(variable_statement);
          result->AddStatement(loop);
          // Parsed for-in loop w/ variable/const declaration.
          return result;
        }

      } else {
        init = variable_statement;
      }

    } else {
      Expression* expression = ParseExpression(false, CHECK_OK);
      if (peek() == Token::IN) {
        // Signal a reference error if the expression is an invalid
        // left-hand side expression.  We could report this as a syntax
        // error here but for compatibility with JSC we choose to report
        // the error at runtime.
        if (expression == NULL || !expression->IsValidLeftHandSide()) {
          Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
          expression = NewThrowReferenceError(type);
        }
        ForInStatement* loop = NEW(ForInStatement(labels));
        Target target(this, loop);

        Expect(Token::IN, CHECK_OK);
        Expression* enumerable = ParseExpression(true, CHECK_OK);
        Expect(Token::RPAREN, CHECK_OK);

        Statement* body = ParseStatement(NULL, CHECK_OK);
        if (loop) loop->Initialize(expression, enumerable, body);

        // Parsed for-in loop.
        return loop;

      } else {
        init = NEW(ExpressionStatement(expression));
      }
    }
  }

  // Standard 'for' loop
  ForStatement* loop = NEW(ForStatement(labels));
  Target target(this, loop);

  // Parsed initializer at this point.
  Expect(Token::SEMICOLON, CHECK_OK);

  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 = NEW(ExpressionStatement(exp));
  }
  Expect(Token::RPAREN, CHECK_OK);

  Statement* body = ParseStatement(NULL, CHECK_OK);

  if (loop) loop->Initialize(init, cond, next, body);
  return loop;
}


// Precedence = 1
Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
  // Expression ::
  //   AssignmentExpression
  //   Expression ',' AssignmentExpression

  Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
  while (peek() == Token::COMMA) {
    Expect(Token::COMMA, CHECK_OK);
    Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
    result = NEW(BinaryOperation(Token::COMMA, result, right));
  }
  return result;
}


// Precedence = 2
Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
  // AssignmentExpression ::
  //   ConditionalExpression
  //   LeftHandSideExpression AssignmentOperator AssignmentExpression

  Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);

  if (!Token::IsAssignmentOp(peek())) {
    // Parsed conditional expression only (no assignment).
    return expression;
  }

  // Signal a reference error if the expression is an invalid left-hand
  // side expression.  We could report this as a syntax error here but
  // for compatibility with JSC we choose to report the error at
  // runtime.
  if (expression == NULL || !expression->IsValidLeftHandSide()) {
    Handle<String> type = Factory::invalid_lhs_in_assignment_symbol();
    expression = NewThrowReferenceError(type);
  }

  Token::Value op = Next();  // Get assignment operator.
  int pos = scanner().location().beg_pos;
  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);

  // 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.
  Property* property = expression ? expression->AsProperty() : NULL;
  if (op == Token::ASSIGN &&
      property != NULL &&
      property->obj()->AsVariableProxy() != NULL &&
      property->obj()->AsVariableProxy()->is_this()) {
    temp_scope_->AddProperty();
  }

  return NEW(Assignment(op, expression, right, pos));
}


// Precedence = 3
Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
  // ConditionalExpression ::
  //   LogicalOrExpression
  //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression

  // We start using the binary expression parser for prec >= 4 only!
  Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
  if (peek() != Token::CONDITIONAL) return expression;
  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.
  Expression* left = ParseAssignmentExpression(true, CHECK_OK);
  Expect(Token::COLON, CHECK_OK);
  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
  return NEW(Conditional(expression, left, right));
}


static int Precedence(Token::Value tok, bool accept_IN) {
  if (tok == Token::IN && !accept_IN)
    return 0;  // 0 precedence will terminate binary expression parsing

  return Token::Precedence(tok);
}


// Precedence >= 4
Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
  ASSERT(prec >= 4);
  Expression* x = ParseUnaryExpression(CHECK_OK);
  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
    // prec1 >= 4
    while (Precedence(peek(), accept_IN) == prec1) {
      Token::Value op = Next();
      Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);

      // Compute some expressions involving only number literals.
      if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
          y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
        double x_val = x->AsLiteral()->handle()->Number();
        double y_val = y->AsLiteral()->handle()->Number();

        switch (op) {
          case Token::ADD:
            x = NewNumberLiteral(x_val + y_val);
            continue;
          case Token::SUB:
            x = NewNumberLiteral(x_val - y_val);
            continue;
          case Token::MUL:
            x = NewNumberLiteral(x_val * y_val);
            continue;
          case Token::DIV:
            x = NewNumberLiteral(x_val / y_val);
            continue;
          case Token::BIT_OR:
            x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
            continue;
          case Token::BIT_AND:
            x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
            continue;
          case Token::BIT_XOR:
            x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
            continue;
          case Token::SHL: {
            int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
            x = NewNumberLiteral(value);
            continue;
          }
          case Token::SHR: {
            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
            uint32_t value = DoubleToUint32(x_val) >> shift;
            x = NewNumberLiteral(value);
            continue;
          }
          case Token::SAR: {
            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
            int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
            x = NewNumberLiteral(value);
            continue;
          }
          default:
            break;
        }
      }

      // Convert constant divisions to multiplications for speed.
      if (op == Token::DIV &&
          y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
        double y_val = y->AsLiteral()->handle()->Number();
        int64_t y_int = static_cast<int64_t>(y_val);
        // There are rounding issues with this optimization, but they don't
        // apply if the number to be divided with has a reciprocal that can be
        // precisely represented as a floating point number.  This is the case
        // if the number is an integer power of 2.  Negative integer powers of
        // 2 work too, but for -2, -1, 1 and 2 we don't do the strength
        // reduction because the inlined optimistic idiv has a reasonable
        // chance of succeeding by producing a Smi answer with no remainder.
        if (static_cast<double>(y_int) == y_val &&
            (IsPowerOf2(y_int) || IsPowerOf2(-y_int)) &&
            (y_int > 2 || y_int < -2)) {
          y = NewNumberLiteral(1 / y_val);
          op = Token::MUL;
        }
      }

      // For now we distinguish between comparisons and other binary
      // operations.  (We could combine the two and get rid of this
      // code an 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;
        }
        x = NEW(CompareOperation(cmp, x, y));
        if (cmp != op) {
          // The comparison was negated - add a NOT.
          x = NEW(UnaryOperation(Token::NOT, x));
        }

      } else {
        // We have a "normal" binary operation.
        x = NEW(BinaryOperation(op, x, y));
      }
    }
  }
  return x;
}


Expression* Parser::ParseUnaryExpression(bool* ok) {
  // UnaryExpression ::
  //   PostfixExpression
  //   'delete' UnaryExpression
  //   'void' UnaryExpression
  //   'typeof' UnaryExpression
  //   '++' UnaryExpression
  //   '--' UnaryExpression
  //   '+' UnaryExpression
  //   '-' UnaryExpression
  //   '~' UnaryExpression
  //   '!' UnaryExpression

  Token::Value op = peek();
  if (Token::IsUnaryOp(op)) {
    op = Next();
    Expression* expression = ParseUnaryExpression(CHECK_OK);

    // Compute some expressions involving only number literals.
    if (expression != NULL && expression->AsLiteral() &&
        expression->AsLiteral()->handle()->IsNumber()) {
      double value = expression->AsLiteral()->handle()->Number();
      switch (op) {
        case Token::ADD:
          return expression;
        case Token::SUB:
          return NewNumberLiteral(-value);
        case Token::BIT_NOT:
          return NewNumberLiteral(~DoubleToInt32(value));
        default: break;
      }
    }

    return NEW(UnaryOperation(op, expression));

  } else if (Token::IsCountOp(op)) {
    op = Next();
    Expression* expression = ParseUnaryExpression(CHECK_OK);
    // Signal a reference error if the expression is an invalid
    // left-hand side expression.  We could report this as a syntax
    // error here but for compatibility with JSC we choose to report the
    // error at runtime.
    if (expression == NULL || !expression->IsValidLeftHandSide()) {
      Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
      expression = NewThrowReferenceError(type);
    }
    return NEW(CountOperation(true /* prefix */, op, expression));

  } else {
    return ParsePostfixExpression(ok);
  }
}


Expression* Parser::ParsePostfixExpression(bool* ok) {
  // PostfixExpression ::
  //   LeftHandSideExpression ('++' | '--')?

  Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
  if (!scanner_.has_line_terminator_before_next() && Token::IsCountOp(peek())) {
    // Signal a reference error if the expression is an invalid
    // left-hand side expression.  We could report this as a syntax
    // error here but for compatibility with JSC we choose to report the
    // error at runtime.
    if (expression == NULL || !expression->IsValidLeftHandSide()) {
      Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
      expression = NewThrowReferenceError(type);
    }
    Token::Value next = Next();
    expression = NEW(CountOperation(false /* postfix */, next, expression));
  }
  return expression;
}


Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
  // LeftHandSideExpression ::
  //   (NewExpression | MemberExpression) ...

  Expression* result;
  if (peek() == Token::NEW) {
    result = ParseNewExpression(CHECK_OK);
  } else {
    result = ParseMemberExpression(CHECK_OK);
  }

  while (true) {
    switch (peek()) {
      case Token::LBRACK: {
        Consume(Token::LBRACK);
        int pos = scanner().location().beg_pos;
        Expression* index = ParseExpression(true, CHECK_OK);
        result = factory()->NewProperty(result, index, pos);
        Expect(Token::RBRACK, CHECK_OK);
        break;
      }

      case Token::LPAREN: {
        int pos = scanner().location().beg_pos;
        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);

        // Keep track of eval() calls since they disable all local variable
        // optimizations.
        // The calls that need special treatment are the
        // direct (i.e. not aliased) eval calls. These calls are all of the
        // form eval(...) with no explicit receiver object where eval is not
        // declared in the current scope chain. These calls are marked as
        // potentially direct eval calls. Whether they are actually direct calls
        // to eval is determined at run time.
        if (!is_pre_parsing_) {
          VariableProxy* callee = result->AsVariableProxy();
          if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
            Handle<String> name = callee->name();
            Variable* var = top_scope_->Lookup(name);
            if (var == NULL) {
              top_scope_->RecordEvalCall();
            }
          }
        }
        result = factory()->NewCall(result, args, pos);
        break;
      }

      case Token::PERIOD: {
        Consume(Token::PERIOD);
        int pos = scanner().location().beg_pos;
        Handle<String> name = ParseIdentifier(CHECK_OK);
        result = factory()->NewProperty(result, NEW(Literal(name)), pos);
        break;
      }

      default:
        return result;
    }
  }
}



Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
  // NewExpression ::
  //   ('new')+ MemberExpression

  // The grammar for new expressions is pretty warped. The keyword
  // 'new' can either be a part of the new expression (where it isn't
  // followed by an argument list) or a part of the member expression,
  // where it must be followed by an argument list. To accommodate
  // this, we parse the 'new' keywords greedily and keep track of how
  // many we have parsed. This information is then passed on to the
  // member expression parser, which is only allowed to match argument
  // lists as long as it has 'new' prefixes left
  Expect(Token::NEW, CHECK_OK);
  PositionStack::Element pos(stack, scanner().location().beg_pos);

  Expression* result;
  if (peek() == Token::NEW) {
    result = ParseNewPrefix(stack, CHECK_OK);
  } else {
    result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
  }

  if (!stack->is_empty()) {
    int last = stack->pop();
    result = NEW(CallNew(result, new ZoneList<Expression*>(0), last));
  }
  return result;
}


Expression* Parser::ParseNewExpression(bool* ok) {
  PositionStack stack(ok);
  return ParseNewPrefix(&stack, ok);
}


Expression* Parser::ParseMemberExpression(bool* ok) {
  return ParseMemberWithNewPrefixesExpression(NULL, ok);
}


Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
                                                         bool* ok) {
  // MemberExpression ::
  //   (PrimaryExpression | FunctionLiteral)
  //     ('[' Expression ']' | '.' Identifier | Arguments)*

  // Parse the initial primary or function expression.
  Expression* result = NULL;
  if (peek() == Token::FUNCTION) {
    Expect(Token::FUNCTION, CHECK_OK);
    int function_token_position = scanner().location().beg_pos;
    Handle<String> name;
    if (peek() == Token::IDENTIFIER) name = ParseIdentifier(CHECK_OK);
    result = ParseFunctionLiteral(name, function_token_position,
                                  NESTED, CHECK_OK);
  } else {
    result = ParsePrimaryExpression(CHECK_OK);
  }

  while (true) {
    switch (peek()) {
      case Token::LBRACK: {
        Consume(Token::LBRACK);
        int pos = scanner().location().beg_pos;
        Expression* index = ParseExpression(true, CHECK_OK);
        result = factory()->NewProperty(result, index, pos);
        Expect(Token::RBRACK, CHECK_OK);
        break;
      }
      case Token::PERIOD: {
        Consume(Token::PERIOD);
        int pos = scanner().location().beg_pos;
        Handle<String> name = ParseIdentifier(CHECK_OK);
        result = factory()->NewProperty(result, NEW(Literal(name)), pos);
        break;
      }
      case Token::LPAREN: {
        if ((stack == NULL) || stack->is_empty()) return result;
        // Consume one of the new prefixes (already parsed).
        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
        int last = stack->pop();
        result = NEW(CallNew(result, args, last));
        break;
      }
      default:
        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' ';'

  Expect(Token::DEBUGGER, CHECK_OK);
  ExpectSemicolon(CHECK_OK);
  return NEW(DebuggerStatement());
}


void Parser::ReportUnexpectedToken(Token::Value token) {
  // We don't report stack overflows here, to avoid increasing the
  // stack depth even further.  Instead we report it after parsing is
  // over, in ParseProgram.
  if (token == Token::ILLEGAL && scanner().stack_overflow())
    return;
  // Four of the tokens are treated specially
  switch (token) {
  case Token::EOS:
    return ReportMessage("unexpected_eos", Vector<const char*>::empty());
  case Token::NUMBER:
    return ReportMessage("unexpected_token_number",
                         Vector<const char*>::empty());
  case Token::STRING:
    return ReportMessage("unexpected_token_string",
                         Vector<const char*>::empty());
  case Token::IDENTIFIER:
    return ReportMessage("unexpected_token_identifier",
                         Vector<const char*>::empty());
  default:
    const char* name = Token::String(token);
    ASSERT(name != NULL);
    ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
  }
}


Expression* Parser::ParsePrimaryExpression(bool* ok) {
  // PrimaryExpression ::
  //   'this'
  //   'null'
  //   'true'
  //   'false'
  //   Identifier
  //   Number
  //   String
  //   ArrayLiteral
  //   ObjectLiteral
  //   RegExpLiteral
  //   '(' Expression ')'

  Expression* result = NULL;
  switch (peek()) {
    case Token::THIS: {
      Consume(Token::THIS);
      if (is_pre_parsing_) {
        result = VariableProxySentinel::this_proxy();
      } else {
        VariableProxy* recv = top_scope_->receiver();
        recv->var_uses()->RecordRead(1);
        result = recv;
      }
      break;
    }

    case Token::NULL_LITERAL:
      Consume(Token::NULL_LITERAL);
      result = NEW(Literal(Factory::null_value()));
      break;

    case Token::TRUE_LITERAL:
      Consume(Token::TRUE_LITERAL);
      result = NEW(Literal(Factory::true_value()));
      break;

    case Token::FALSE_LITERAL:
      Consume(Token::FALSE_LITERAL);
      result = NEW(Literal(Factory::false_value()));
      break;

    case Token::IDENTIFIER: {
      Handle<String> name = ParseIdentifier(CHECK_OK);
      if (is_pre_parsing_) {
        result = VariableProxySentinel::identifier_proxy();
      } else {
        result = top_scope_->NewUnresolved(name, inside_with());
      }
      break;
    }

    case Token::NUMBER: {
      Consume(Token::NUMBER);
      double value =
        StringToDouble(scanner_.literal_string(), ALLOW_HEX | ALLOW_OCTALS);
      result = NewNumberLiteral(value);
      break;
    }

    case Token::STRING: {
      Consume(Token::STRING);
      Handle<String> symbol =
          factory()->LookupSymbol(scanner_.literal_string(),
                                  scanner_.literal_length());
      result = NEW(Literal(symbol));
      break;
    }

    case Token::ASSIGN_DIV:
      result = ParseRegExpLiteral(true, CHECK_OK);
      break;

    case Token::DIV:
      result = ParseRegExpLiteral(false, CHECK_OK);
      break;

    case Token::LBRACK:
      result = ParseArrayLiteral(CHECK_OK);
      break;

    case Token::LBRACE:
      result = ParseObjectLiteral(CHECK_OK);
      break;

    case Token::LPAREN:
      Consume(Token::LPAREN);
      result = ParseExpression(true, CHECK_OK);
      Expect(Token::RPAREN, CHECK_OK);
      break;

    case Token::MOD:
      if (allow_natives_syntax_ || extension_ != NULL) {
        result = ParseV8Intrinsic(CHECK_OK);
        break;
      }
      // If we're not allowing special syntax we fall-through to the
      // default case.

    default: {
      Token::Value tok = peek();
      // Token::Peek returns the value of the next token but
      // location() gives info about the current token.
      // Therefore, we need to read ahead to the next token
      Next();
      ReportUnexpectedToken(tok);
      *ok = false;
      return NULL;
    }
  }

  return result;
}


Expression* Parser::ParseArrayLiteral(bool* ok) {
  // ArrayLiteral ::
  //   '[' Expression? (',' Expression?)* ']'

  ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4);
  Expect(Token::LBRACK, CHECK_OK);
  while (peek() != Token::RBRACK) {
    Expression* elem;
    if (peek() == Token::COMMA) {
      elem = GetLiteralTheHole();
    } else {
      elem = ParseAssignmentExpression(true, CHECK_OK);
    }
    values.Add(elem);
    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 = temp_scope_->NextMaterializedLiteralIndex();

  if (is_pre_parsing_) return NULL;

  // Allocate a fixed array with all the literals.
  Handle<FixedArray> literals =
      Factory::NewFixedArray(values.length(), TENURED);

  // Fill in the literals.
  bool is_simple = true;
  int depth = 1;
  for (int i = 0; i < values.length(); i++) {
    MaterializedLiteral* m_literal = values.at(i)->AsMaterializedLiteral();
    if (m_literal != NULL && m_literal->depth() + 1 > depth) {
      depth = m_literal->depth() + 1;
    }
    Handle<Object> boilerplate_value = GetBoilerplateValue(values.at(i));
    if (boilerplate_value->IsUndefined()) {
      literals->set_the_hole(i);
      is_simple = false;
    } else {
      literals->set(i, *boilerplate_value);
    }
  }

  return NEW(ArrayLiteral(literals, values.elements(),
                          literal_index, is_simple, depth));
}


bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
  return property != NULL &&
         property->kind() != ObjectLiteral::Property::PROTOTYPE;
}


bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
  return lit != NULL && lit->is_simple();
}

Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
  ASSERT(IsCompileTimeValue(expression));
  Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
  ObjectLiteral* object_literal = expression->AsObjectLiteral();
  if (object_literal != NULL) {
    ASSERT(object_literal->is_simple());
    result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL));
    result->set(kElementsSlot, *object_literal->constant_properties());
  } else {
    ArrayLiteral* array_literal = expression->AsArrayLiteral();
    ASSERT(array_literal != NULL && array_literal->is_simple());
    result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
    result->set(kElementsSlot, *array_literal->literals());
  }
  return result;
}


CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
  Smi* type_value = Smi::cast(value->get(kTypeSlot));
  return static_cast<Type>(type_value->value());
}


Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
}


Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
  if (expression->AsLiteral() != NULL) {
    return expression->AsLiteral()->handle();
  }
  if (CompileTimeValue::IsCompileTimeValue(expression)) {
    return CompileTimeValue::GetValue(expression);
  }
  return Factory::undefined_value();
}


Expression* Parser::ParseObjectLiteral(bool* ok) {
  // ObjectLiteral ::
  //   '{' (
  //       ((Identifier | String | Number) ':' AssignmentExpression)
  //     | (('get' | 'set') FunctionLiteral)
  //    )*[','] '}'

  ZoneListWrapper<ObjectLiteral::Property> properties =
      factory()->NewList<ObjectLiteral::Property>(4);
  int number_of_boilerplate_properties = 0;

  Expect(Token::LBRACE, CHECK_OK);
  while (peek() != Token::RBRACE) {
    Literal* key = NULL;
    switch (peek()) {
      case Token::IDENTIFIER: {
        // Store identifier keys as literal symbols to avoid
        // resolving them when compiling code for the object
        // literal.
        bool is_getter = false;
        bool is_setter = false;
        Handle<String> id =
            ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
        if (is_getter || is_setter) {
          // Special handling of getter and setter syntax.
          if (peek() == Token::IDENTIFIER) {
            Handle<String> name = ParseIdentifier(CHECK_OK);
            FunctionLiteral* value =
                ParseFunctionLiteral(name, RelocInfo::kNoPosition,
                                     DECLARATION, CHECK_OK);
            ObjectLiteral::Property* property =
                NEW(ObjectLiteral::Property(is_getter, value));
            if (IsBoilerplateProperty(property))
              number_of_boilerplate_properties++;
            properties.Add(property);
            if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
            continue;  // restart the while
          }
        }
        key = NEW(Literal(id));
        break;
      }

      case Token::STRING: {
        Consume(Token::STRING);
        Handle<String> string =
            factory()->LookupSymbol(scanner_.literal_string(),
                                    scanner_.literal_length());
        uint32_t index;
        if (!string.is_null() && string->AsArrayIndex(&index)) {
          key = NewNumberLiteral(index);
        } else {
          key = NEW(Literal(string));
        }
        break;
      }

      case Token::NUMBER: {
        Consume(Token::NUMBER);
        double value =
          StringToDouble(scanner_.literal_string(), ALLOW_HEX | ALLOW_OCTALS);
        key = NewNumberLiteral(value);
        break;
      }

      default:
        Expect(Token::RBRACE, CHECK_OK);
        break;
    }

    Expect(Token::COLON, CHECK_OK);
    Expression* value = ParseAssignmentExpression(true, CHECK_OK);

    ObjectLiteral::Property* property =
        NEW(ObjectLiteral::Property(key, value));

    // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
    if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
    properties.Add(property);

    // TODO(1240767): Consider allowing trailing comma.
    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
  }
  Expect(Token::RBRACE, CHECK_OK);
  // Computation of literal_index must happen before pre parse bailout.
  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
  if (is_pre_parsing_) return NULL;

  Handle<FixedArray> constant_properties =
      Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
  int position = 0;
  bool is_simple = true;
  int depth = 1;
  for (int i = 0; i < properties.length(); i++) {
    ObjectLiteral::Property* property = properties.at(i);
    if (!IsBoilerplateProperty(property)) {
      is_simple = false;
      continue;
    }
    MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
    if (m_literal != NULL && m_literal->depth() + 1 > depth) {
      depth = m_literal->depth() + 1;
    }

    // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
    // value for COMPUTED properties, the real value is filled in at
    // runtime. The enumeration order is maintained.
    Handle<Object> key = property->key()->handle();
    Handle<Object> value = GetBoilerplateValue(property->value());
    is_simple = is_simple && !value->IsUndefined();

    // Add name, value pair to the fixed array.
    constant_properties->set(position++, *key);
    constant_properties->set(position++, *value);
  }

  return new ObjectLiteral(constant_properties,
                           properties.elements(),
                           literal_index,
                           is_simple,
                           depth);
}


Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
  if (!scanner_.ScanRegExpPattern(seen_equal)) {
    Next();
    ReportMessage("unterminated_regexp", Vector<const char*>::empty());
    *ok = false;
    return NULL;
  }

  int literal_index = temp_scope_->NextMaterializedLiteralIndex();

  if (is_pre_parsing_) {
    // If we're preparsing we just do all the parsing stuff without
    // building anything.
    if (!scanner_.ScanRegExpFlags()) {
      Next();
      ReportMessage("invalid_regexp_flags", Vector<const char*>::empty());
      *ok = false;
      return NULL;
    }
    Next();
    return NULL;
  }

  Handle<String> js_pattern =
      Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED);
  scanner_.ScanRegExpFlags();
  Handle<String> js_flags =
      Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED);
  Next();

  return new RegExpLiteral(js_pattern, js_flags, literal_index);
}


ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
  // Arguments ::
  //   '(' (AssignmentExpression)*[','] ')'

  ZoneListWrapper<Expression> result = factory()->NewList<Expression>(4);
  Expect(Token::LPAREN, CHECK_OK);
  bool done = (peek() == Token::RPAREN);
  while (!done) {
    Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
    result.Add(argument);
    done = (peek() == Token::RPAREN);
    if (!done) Expect(Token::COMMA, CHECK_OK);
  }
  Expect(Token::RPAREN, CHECK_OK);
  return result.elements();
}


FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
                                              int function_token_position,
                                              FunctionLiteralType type,
                                              bool* ok) {
  // Function ::
  //   '(' FormalParameterList? ')' '{' FunctionBody '}'

  bool is_named = !var_name.is_null();

  // The name associated with this function. If it's a function expression,
  // this is the actual function name, otherwise this is the name of the
  // variable declared and initialized with the function (expression). In
  // that case, we don't have a function name (it's empty).
  Handle<String> name = is_named ? var_name : factory()->EmptySymbol();
  // The function name, if any.
  Handle<String> function_name = factory()->EmptySymbol();
  if (is_named && (type == EXPRESSION || type == NESTED)) {
    function_name = name;
  }

  int num_parameters = 0;
  // Parse function body.
  { Scope::Type type = Scope::FUNCTION_SCOPE;
    Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
    LexicalScope lexical_scope(this, scope);
    TemporaryScope temp_scope(this);
    top_scope_->SetScopeName(name);

    //  FormalParameterList ::
    //    '(' (Identifier)*[','] ')'
    Expect(Token::LPAREN, CHECK_OK);
    int start_pos = scanner_.location().beg_pos;
    bool done = (peek() == Token::RPAREN);
    while (!done) {
      Handle<String> param_name = ParseIdentifier(CHECK_OK);
      if (!is_pre_parsing_) {
        top_scope_->AddParameter(top_scope_->DeclareLocal(param_name,
                                                          Variable::VAR));
        num_parameters++;
      }
      done = (peek() == Token::RPAREN);
      if (!done) Expect(Token::COMMA, CHECK_OK);
    }
    Expect(Token::RPAREN, CHECK_OK);

    Expect(Token::LBRACE, CHECK_OK);
    ZoneListWrapper<Statement> body = factory()->NewList<Statement>(8);

    // 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).
    // 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 Proxis as is the case now.
    if (!function_name.is_null() && function_name->length() > 0) {
      Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
      VariableProxy* fproxy =
          top_scope_->NewUnresolved(function_name, inside_with());
      fproxy->BindTo(fvar);
      body.Add(new ExpressionStatement(
                   new Assignment(Token::INIT_VAR, fproxy,
                                  NEW(ThisFunction()),
                                  RelocInfo::kNoPosition)));
    }

    // Determine if the function will be lazily compiled. The mode can
    // only be PARSE_LAZILY if the --lazy flag is true.
    bool is_lazily_compiled =
        mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext();

    int materialized_literal_count;
    int expected_property_count;
    bool only_this_property_assignments;
    bool only_simple_this_property_assignments;
    Handle<FixedArray> this_property_assignments;
    if (is_lazily_compiled && pre_data() != NULL) {
      FunctionEntry entry = pre_data()->GetFunctionEnd(start_pos);
      int end_pos = entry.end_pos();
      Counters::total_preparse_skipped.Increment(end_pos - start_pos);
      scanner_.SeekForward(end_pos);
      materialized_literal_count = entry.literal_count();
      expected_property_count = entry.property_count();
      only_this_property_assignments = false;
      only_simple_this_property_assignments = false;
      this_property_assignments = Factory::empty_fixed_array();
    } else {
      ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
      materialized_literal_count = temp_scope.materialized_literal_count();
      expected_property_count = temp_scope.expected_property_count();
      only_this_property_assignments =
          temp_scope.only_this_property_assignments();
      only_simple_this_property_assignments =
          temp_scope.only_simple_this_property_assignments();
      this_property_assignments = temp_scope.this_property_assignments();
    }

    Expect(Token::RBRACE, CHECK_OK);
    int end_pos = scanner_.location().end_pos;

    FunctionEntry entry = log()->LogFunction(start_pos);
    if (entry.is_valid()) {
      entry.set_end_pos(end_pos);
      entry.set_literal_count(materialized_literal_count);
      entry.set_property_count(expected_property_count);
    }

    FunctionLiteral* function_literal =
        NEW(FunctionLiteral(name,
                            top_scope_,
                            body.elements(),
                            materialized_literal_count,
                            expected_property_count,
                            only_this_property_assignments,
                            only_simple_this_property_assignments,
                            this_property_assignments,
                            num_parameters,
                            start_pos,
                            end_pos,
                            function_name->length() > 0));
    if (!is_pre_parsing_) {
      function_literal->set_function_token_position(function_token_position);
    }
    return function_literal;
  }
}


Expression* Parser::ParseV8Intrinsic(bool* ok) {
  // CallRuntime ::
  //   '%' Identifier Arguments

  Expect(Token::MOD, CHECK_OK);
  Handle<String> name = ParseIdentifier(CHECK_OK);
  Runtime::Function* function =
      Runtime::FunctionForName(scanner_.literal_string());
  ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
  if (function == NULL && extension_ != NULL) {
    // The extension structures are only accessible while parsing the
    // very first time not when reparsing because of lazy compilation.
    top_scope_->ForceEagerCompilation();
  }

  // Check for built-in macros.
  if (!is_pre_parsing_) {
    if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
      // %IS_VAR(x)
      //   evaluates to x if x is a variable,
      //   leads to a parse error otherwise
      if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
        return args->at(0);
      }
      *ok = false;
    // Check here for other macros.
    // } else if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
    //   ...
    }

    if (!*ok) {
      // We found a macro but it failed.
      ReportMessage("unable_to_parse", Vector<const char*>::empty());
      return NULL;
    }
  }

  // Otherwise we have a runtime call.
  return NEW(CallRuntime(name, function, args));
}


void Parser::Consume(Token::Value token) {
  Token::Value next = Next();
  USE(next);
  USE(token);
  ASSERT(next == token);
}


void Parser::Expect(Token::Value token, bool* ok) {
  Token::Value next = Next();
  if (next == token) return;
  ReportUnexpectedToken(next);
  *ok = false;
}


void Parser::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_.has_line_terminator_before_next() ||
      tok == Token::RBRACE ||
      tok == Token::EOS) {
    return;
  }
  Expect(Token::SEMICOLON, ok);
}


Literal* Parser::GetLiteralUndefined() {
  return NEW(Literal(Factory::undefined_value()));
}


Literal* Parser::GetLiteralTheHole() {
  return NEW(Literal(Factory::the_hole_value()));
}


Literal* Parser::GetLiteralNumber(double value) {
  return NewNumberLiteral(value);
}


Handle<String> Parser::ParseIdentifier(bool* ok) {
  Expect(Token::IDENTIFIER, ok);
  if (!*ok) return Handle<String>();
  return factory()->LookupSymbol(scanner_.literal_string(),
                                 scanner_.literal_length());
}

// This function reads an identifier and determines whether or not it
// is 'get' or 'set'.  The reason for not using ParseIdentifier and
// checking on the output is that this involves heap allocation which
// we can't do during preparsing.
Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
                                                 bool* is_set,
                                                 bool* ok) {
  Expect(Token::IDENTIFIER, ok);
  if (!*ok) return Handle<String>();
  if (scanner_.literal_length() == 3) {
    const char* token = scanner_.literal_string();
    *is_get = strcmp(token, "get") == 0;
    *is_set = !*is_get && strcmp(token, "set") == 0;
  }
  return factory()->LookupSymbol(scanner_.literal_string(),
                                 scanner_.literal_length());
}


// ----------------------------------------------------------------------------
// Parser support


bool Parser::TargetStackContainsLabel(Handle<String> label) {
  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
    BreakableStatement* stat = t->node()->AsBreakableStatement();
    if (stat != NULL && ContainsLabel(stat->labels(), label))
      return true;
  }
  return false;
}


BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
  bool anonymous = label.is_null();
  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
    BreakableStatement* stat = t->node()->AsBreakableStatement();
    if (stat == NULL) continue;
    if ((anonymous && stat->is_target_for_anonymous()) ||
        (!anonymous && ContainsLabel(stat->labels(), label))) {
      RegisterTargetUse(stat->break_target(), t->previous());
      return stat;
    }
  }
  return NULL;
}


IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
                                                 bool* ok) {
  bool anonymous = label.is_null();
  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
    IterationStatement* stat = t->node()->AsIterationStatement();
    if (stat == NULL) continue;

    ASSERT(stat->is_target_for_anonymous());
    if (anonymous || ContainsLabel(stat->labels(), label)) {
      RegisterTargetUse(stat->continue_target(), t->previous());
      return stat;
    }
  }
  return NULL;
}


void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) {
  // Register that a break target found at the given stop in the
  // target stack has been used from the top of the target stack. Add
  // the break target to any TargetCollectors passed on the stack.
  for (Target* t = target_stack_; t != stop; t = t->previous()) {
    TargetCollector* collector = t->node()->AsTargetCollector();
    if (collector != NULL) collector->AddTarget(target);
  }
}


Literal* Parser::NewNumberLiteral(double number) {
  return NEW(Literal(Factory::NewNumber(number, TENURED)));
}


Expression* Parser::NewThrowReferenceError(Handle<String> type) {
  return NewThrowError(Factory::MakeReferenceError_symbol(),
                       type, HandleVector<Object>(NULL, 0));
}


Expression* Parser::NewThrowSyntaxError(Handle<String> type,
                                        Handle<Object> first) {
  int argc = first.is_null() ? 0 : 1;
  Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
  return NewThrowError(Factory::MakeSyntaxError_symbol(), type, arguments);
}


Expression* Parser::NewThrowTypeError(Handle<String> type,
                                      Handle<Object> first,
                                      Handle<Object> second) {
  ASSERT(!first.is_null() && !second.is_null());
  Handle<Object> elements[] = { first, second };
  Vector< Handle<Object> > arguments =
      HandleVector<Object>(elements, ARRAY_SIZE(elements));
  return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments);
}


Expression* Parser::NewThrowError(Handle<String> constructor,
                                  Handle<String> type,
                                  Vector< Handle<Object> > arguments) {
  if (is_pre_parsing_) return NULL;

  int argc = arguments.length();
  Handle<JSArray> array = Factory::NewJSArray(argc, TENURED);
  ASSERT(array->IsJSArray() && array->HasFastElements());
  for (int i = 0; i < argc; i++) {
    Handle<Object> element = arguments[i];
    if (!element.is_null()) {
      array->SetFastElement(i, *element);
    }
  }
  ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
  args->Add(new Literal(type));
  args->Add(new Literal(array));
  return new Throw(new CallRuntime(constructor, NULL, args),
                   scanner().location().beg_pos);
}


// ----------------------------------------------------------------------------
// Regular expressions


RegExpParser::RegExpParser(FlatStringReader* in,
                           Handle<String>* error,
                           bool multiline)
  : current_(kEndMarker),
    has_more_(true),
    multiline_(multiline),
    next_pos_(0),
    in_(in),
    error_(error),
    simple_(false),
    contains_anchor_(false),
    captures_(NULL),
    is_scanned_for_captures_(false),
    capture_count_(0),
    failed_(false) {
  Advance(1);
}


uc32 RegExpParser::Next() {
  if (has_next()) {
    return in()->Get(next_pos_);
  } else {
    return kEndMarker;
  }
}


void RegExpParser::Advance() {
  if (next_pos_ < in()->length()) {
    StackLimitCheck check;
    if (check.HasOverflowed()) {
      ReportError(CStrVector(Top::kStackOverflowMessage));
    } else if (Zone::excess_allocation()) {
      ReportError(CStrVector("Regular expression too large"));
    } else {
      current_ = in()->Get(next_pos_);
      next_pos_++;
    }
  } else {
    current_ = kEndMarker;
    has_more_ = false;
  }
}


void RegExpParser::Reset(int pos) {
  next_pos_ = pos;
  Advance();
}


void RegExpParser::Advance(int dist) {
  for (int i = 0; i < dist; i++)
    Advance();
}


bool RegExpParser::simple() {
  return simple_;
}

RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
  failed_ = true;
  *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
  // Zip to the end to make sure the no more input is read.
  current_ = kEndMarker;
  next_pos_ = in()->length();
  return NULL;
}


// Pattern ::
//   Disjunction
RegExpTree* RegExpParser::ParsePattern() {
  RegExpTree* result = ParseDisjunction(CHECK_FAILED);
  ASSERT(!has_more());
  // If the result of parsing is a literal string atom, and it has the
  // same length as the input, then the atom is identical to the input.
  if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
    simple_ = true;
  }
  return result;
}


// Disjunction ::
//   Alternative
//   Alternative | Disjunction
// Alternative ::
//   [empty]
//   Term Alternative
// Term ::
//   Assertion
//   Atom
//   Atom Quantifier
RegExpTree* RegExpParser::ParseDisjunction() {
  // Used to store current state while parsing subexpressions.
  RegExpParserState initial_state(NULL, INITIAL, 0);
  RegExpParserState* stored_state = &initial_state;
  // Cache the builder in a local variable for quick access.
  RegExpBuilder* builder = initial_state.builder();
  while (true) {
    switch (current()) {
    case kEndMarker:
      if (stored_state->IsSubexpression()) {
        // Inside a parenthesized group when hitting end of input.
        ReportError(CStrVector("Unterminated group") CHECK_FAILED);
      }
      ASSERT_EQ(INITIAL, stored_state->group_type());
      // Parsing completed successfully.
      return builder->ToRegExp();
    case ')': {
      if (!stored_state->IsSubexpression()) {
        ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
      }
      ASSERT_NE(INITIAL, stored_state->group_type());

      Advance();
      // End disjunction parsing and convert builder content to new single
      // regexp atom.
      RegExpTree* body = builder->ToRegExp();

      int end_capture_index = captures_started();

      int capture_index = stored_state->capture_index();
      SubexpressionType type = stored_state->group_type();

      // Restore previous state.
      stored_state = stored_state->previous_state();
      builder = stored_state->builder();

      // Build result of subexpression.
      if (type == CAPTURE) {
        RegExpCapture* capture = new RegExpCapture(body, capture_index);
        captures_->at(capture_index - 1) = capture;
        body = capture;
      } else if (type != GROUPING) {
        ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
        bool is_positive = (type == POSITIVE_LOOKAHEAD);
        body = new RegExpLookahead(body,
                                   is_positive,
                                   end_capture_index - capture_index,
                                   capture_index);
      }
      builder->AddAtom(body);
      break;
    }
    case '|': {
      Advance();
      builder->NewAlternative();
      continue;
    }
    case '*':
    case '+':
    case '?':
      return ReportError(CStrVector("Nothing to repeat"));
    case '^': {
      Advance();
      if (multiline_) {
        builder->AddAssertion(
            new RegExpAssertion(RegExpAssertion::START_OF_LINE));
      } else {
        builder->AddAssertion(
            new RegExpAssertion(RegExpAssertion::START_OF_INPUT));
        set_contains_anchor();
      }
      continue;
    }
    case '$': {
      Advance();
      RegExpAssertion::Type type =
          multiline_ ? RegExpAssertion::END_OF_LINE :
                       RegExpAssertion::END_OF_INPUT;
      builder->AddAssertion(new RegExpAssertion(type));
      continue;
    }
    case '.': {
      Advance();
      // everything except \x0a, \x0d, \u2028 and \u2029
      ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
      CharacterRange::AddClassEscape('.', ranges);
      RegExpTree* atom = new RegExpCharacterClass(ranges, false);
      builder->AddAtom(atom);
      break;
    }
    case '(': {
      SubexpressionType type = CAPTURE;
      Advance();
      if (current() == '?') {
        switch (Next()) {
          case ':':
            type = GROUPING;
            break;
          case '=':
            type = POSITIVE_LOOKAHEAD;
            break;
          case '!':
            type = NEGATIVE_LOOKAHEAD;
            break;
          default:
            ReportError(CStrVector("Invalid group") CHECK_FAILED);
            break;
        }
        Advance(2);
      } else {
        if (captures_ == NULL) {
          captures_ = new ZoneList<RegExpCapture*>(2);
        }
        if (captures_started() >= kMaxCaptures) {
          ReportError(CStrVector("Too many captures") CHECK_FAILED);
        }
        captures_->Add(NULL);
      }
      // Store current state and begin new disjunction parsing.
      stored_state = new RegExpParserState(stored_state,
                                           type,
                                           captures_started());
      builder = stored_state->builder();
      break;
    }
    case '[': {
      RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
      builder->AddAtom(atom);
      break;
    }
    // Atom ::
    //   \ AtomEscape
    case '\\':
      switch (Next()) {
      case kEndMarker:
        return ReportError(CStrVector("\\ at end of pattern"));
      case 'b':
        Advance(2);
        builder->AddAssertion(
            new RegExpAssertion(RegExpAssertion::BOUNDARY));
        continue;
      case 'B':
        Advance(2);
        builder->AddAssertion(
            new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
        continue;
        // AtomEscape ::
        //   CharacterClassEscape
        //
        // CharacterClassEscape :: one of
        //   d D s S w W
      case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
        uc32 c = Next();
        Advance(2);
        ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
        CharacterRange::AddClassEscape(c, ranges);
        RegExpTree* atom = new RegExpCharacterClass(ranges, false);
        builder->AddAtom(atom);
        break;
      }
      case '1': case '2': case '3': case '4': case '5': case '6':
      case '7': case '8': case '9': {
        int index = 0;
        if (ParseBackReferenceIndex(&index)) {
          RegExpCapture* capture = NULL;
          if (captures_ != NULL && index <= captures_->length()) {
            capture = captures_->at(index - 1);
          }
          if (capture == NULL) {
            builder->AddEmpty();
            break;
          }
          RegExpTree* atom = new RegExpBackReference(capture);
          builder->AddAtom(atom);
          break;
        }
        uc32 first_digit = Next();
        if (first_digit == '8' || first_digit == '9') {
          // Treat as identity escape
          builder->AddCharacter(first_digit);
          Advance(2);
          break;
        }
      }
      // FALLTHROUGH
      case '0': {
        Advance();
        uc32 octal = ParseOctalLiteral();
        builder->AddCharacter(octal);
        break;
      }
      // ControlEscape :: one of
      //   f n r t v
      case 'f':
        Advance(2);
        builder->AddCharacter('\f');
        break;
      case 'n':
        Advance(2);
        builder->AddCharacter('\n');
        break;
      case 'r':
        Advance(2);
        builder->AddCharacter('\r');
        break;
      case 't':
        Advance(2);
        builder->AddCharacter('\t');
        break;
      case 'v':
        Advance(2);
        builder->AddCharacter('\v');
        break;
      case 'c': {
        Advance(2);
        uc32 control = ParseControlLetterEscape();
        builder->AddCharacter(control);
        break;
      }
      case 'x': {
        Advance(2);
        uc32 value;
        if (ParseHexEscape(2, &value)) {
          builder->AddCharacter(value);
        } else {
          builder->AddCharacter('x');
        }
        break;
      }
      case 'u': {
        Advance(2);
        uc32 value;
        if (ParseHexEscape(4, &value)) {
          builder->AddCharacter(value);
        } else {
          builder->AddCharacter('u');
        }
        break;
      }
      default:
        // Identity escape.
        builder->AddCharacter(Next());
        Advance(2);
        break;
      }
      break;
    case '{': {
      int dummy;
      if (ParseIntervalQuantifier(&dummy, &dummy)) {
        ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
      }
      // fallthrough
    }
    default:
      builder->AddCharacter(current());
      Advance();
      break;
    }  // end switch(current())

    int min;
    int max;
    switch (current()) {
    // QuantifierPrefix ::
    //   *
    //   +
    //   ?
    //   {
    case '*':
      min = 0;
      max = RegExpTree::kInfinity;
      Advance();
      break;
    case '+':
      min = 1;
      max = RegExpTree::kInfinity;
      Advance();
      break;
    case '?':
      min = 0;
      max = 1;
      Advance();
      break;
    case '{':
      if (ParseIntervalQuantifier(&min, &max)) {
        if (max < min) {
          ReportError(CStrVector("numbers out of order in {} quantifier.")
                      CHECK_FAILED);
        }
        break;
      } else {
        continue;
      }
    default:
      continue;
    }
    bool is_greedy = true;
    if (current() == '?') {
      is_greedy = false;
      Advance();
    }
    builder->AddQuantifierToAtom(min, max, is_greedy);
  }
}

class SourceCharacter {
 public:
  static bool Is(uc32 c) {
    switch (c) {
      // case ']': case '}':
      // In spidermonkey and jsc these are treated as source characters
      // so we do too.
      case '^': case '$': case '\\': case '.': case '*': case '+':
      case '?': case '(': case ')': case '[': case '{': case '|':
      case RegExpParser::kEndMarker:
        return false;
      default:
        return true;
    }
  }
};


static unibrow::Predicate<SourceCharacter> source_character;


static inline bool IsSourceCharacter(uc32 c) {
  return source_character.get(c);
}

#ifdef DEBUG
// Currently only used in an ASSERT.
static bool IsSpecialClassEscape(uc32 c) {
  switch (c) {
    case 'd': case 'D':
    case 's': case 'S':
    case 'w': case 'W':
      return true;
    default:
      return false;
  }
}
#endif


// In order to know whether an escape is a backreference or not we have to scan
// the entire regexp and find the number of capturing parentheses.  However we
// don't want to scan the regexp twice unless it is necessary.  This mini-parser
// is called when needed.  It can see the difference between capturing and
// noncapturing parentheses and can skip character classes and backslash-escaped
// characters.
void RegExpParser::ScanForCaptures() {
  // Start with captures started previous to current position
  int capture_count = captures_started();
  // Add count of captures after this position.
  int n;
  while ((n = current()) != kEndMarker) {
    Advance();
    switch (n) {
      case '\\':
        Advance();
        break;
      case '[': {
        int c;
        while ((c = current()) != kEndMarker) {
          Advance();
          if (c == '\\') {
            Advance();
          } else {
            if (c == ']') break;
          }
        }
        break;
      }
      case '(':
        if (current() != '?') capture_count++;
        break;
    }
  }
  capture_count_ = capture_count;
  is_scanned_for_captures_ = true;
}


bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
  ASSERT_EQ('\\', current());
  ASSERT('1' <= Next() && Next() <= '9');
  // Try to parse a decimal literal that is no greater than the total number
  // of left capturing parentheses in the input.
  int start = position();
  int value = Next() - '0';
  Advance(2);
  while (true) {
    uc32 c = current();
    if (IsDecimalDigit(c)) {
      value = 10 * value + (c - '0');
      if (value > kMaxCaptures) {
        Reset(start);
        return false;
      }
      Advance();
    } else {
      break;
    }
  }
  if (value > captures_started()) {
    if (!is_scanned_for_captures_) {
      int saved_position = position();
      ScanForCaptures();
      Reset(saved_position);
    }
    if (value > capture_count_) {
      Reset(start);
      return false;
    }
  }
  *index_out = value;
  return true;
}


// QuantifierPrefix ::
//   { DecimalDigits }
//   { DecimalDigits , }
//   { DecimalDigits , DecimalDigits }
//
// Returns true if parsing succeeds, and set the min_out and max_out
// values. Values are truncated to RegExpTree::kInfinity if they overflow.
bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
  ASSERT_EQ(current(), '{');
  int start = position();
  Advance();
  int min = 0;
  if (!IsDecimalDigit(current())) {
    Reset(start);
    return false;
  }
  while (IsDecimalDigit(current())) {
    int next = current() - '0';
    if (min > (RegExpTree::kInfinity - next) / 10) {
      // Overflow. Skip past remaining decimal digits and return -1.
      do {
        Advance();
      } while (IsDecimalDigit(current()));
      min = RegExpTree::kInfinity;
      break;
    }
    min = 10 * min + next;
    Advance();
  }
  int max = 0;
  if (current() == '}') {
    max = min;
    Advance();
  } else if (current() == ',') {
    Advance();
    if (current() == '}') {
      max = RegExpTree::kInfinity;
      Advance();
    } else {
      while (IsDecimalDigit(current())) {
        int next = current() - '0';
        if (max > (RegExpTree::kInfinity - next) / 10) {
          do {
            Advance();
          } while (IsDecimalDigit(current()));
          max = RegExpTree::kInfinity;
          break;
        }
        max = 10 * max + next;
        Advance();
      }
      if (current() != '}') {
        Reset(start);
        return false;
      }
      Advance();
    }
  } else {
    Reset(start);
    return false;
  }
  *min_out = min;
  *max_out = max;
  return true;
}


// Upper and lower case letters differ by one bit.
STATIC_CHECK(('a' ^ 'A') == 0x20);

uc32 RegExpParser::ParseControlLetterEscape() {
  if (!has_more())
    return 'c';
  uc32 letter = current() & ~(0x20);  // Collapse upper and lower case letters.
  if (letter < 'A' || 'Z' < letter) {
    // Non-spec error-correction: "\c" followed by non-control letter is
    // interpreted as an IdentityEscape of 'c'.
    return 'c';
  }
  Advance();
  return letter & 0x1f;  // Remainder modulo 32, per specification.
}


uc32 RegExpParser::ParseOctalLiteral() {
  ASSERT('0' <= current() && current() <= '7');
  // For compatibility with some other browsers (not all), we parse
  // up to three octal digits with a value below 256.
  uc32 value = current() - '0';
  Advance();
  if ('0' <= current() && current() <= '7') {
    value = value * 8 + current() - '0';
    Advance();
    if (value < 32 && '0' <= current() && current() <= '7') {
      value = value * 8 + current() - '0';
      Advance();
    }
  }
  return value;
}


bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
  int start = position();
  uc32 val = 0;
  bool done = false;
  for (int i = 0; !done; i++) {
    uc32 c = current();
    int d = HexValue(c);
    if (d < 0) {
      Reset(start);
      return false;
    }
    val = val * 16 + d;
    Advance();
    if (i == length - 1) {
      done = true;
    }
  }
  *value = val;
  return true;
}


uc32 RegExpParser::ParseClassCharacterEscape() {
  ASSERT(current() == '\\');
  ASSERT(has_next() && !IsSpecialClassEscape(Next()));
  Advance();
  switch (current()) {
    case 'b':
      Advance();
      return '\b';
    // ControlEscape :: one of
    //   f n r t v
    case 'f':
      Advance();
      return '\f';
    case 'n':
      Advance();
      return '\n';
    case 'r':
      Advance();
      return '\r';
    case 't':
      Advance();
      return '\t';
    case 'v':
      Advance();
      return '\v';
    case 'c':
      Advance();
      return ParseControlLetterEscape();
    case '0': case '1': case '2': case '3': case '4': case '5':
    case '6': case '7':
      // For compatibility, we interpret a decimal escape that isn't
      // a back reference (and therefore either \0 or not valid according
      // to the specification) as a 1..3 digit octal character code.
      return ParseOctalLiteral();
    case 'x': {
      Advance();
      uc32 value;
      if (ParseHexEscape(2, &value)) {
        return value;
      }
      // If \x is not followed by a two-digit hexadecimal, treat it
      // as an identity escape.
      return 'x';
    }
    case 'u': {
      Advance();
      uc32 value;
      if (ParseHexEscape(4, &value)) {
        return value;
      }
      // If \u is not followed by a four-digit hexadecimal, treat it
      // as an identity escape.
      return 'u';
    }
    default: {
      // Extended identity escape. We accept any character that hasn't
      // been matched by a more specific case, not just the subset required
      // by the ECMAScript specification.
      uc32 result = current();
      Advance();
      return result;
    }
  }
  return 0;
}


CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
  ASSERT_EQ(0, *char_class);
  uc32 first = current();
  if (first == '\\') {
    switch (Next()) {
      case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
        *char_class = Next();
        Advance(2);
        return CharacterRange::Singleton(0);  // Return dummy value.
      }
      case kEndMarker:
        return ReportError(CStrVector("\\ at end of pattern"));
      default:
        uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
        return CharacterRange::Singleton(c);
    }
  } else {
    Advance();
    return CharacterRange::Singleton(first);
  }
}


RegExpTree* RegExpParser::ParseCharacterClass() {
  static const char* kUnterminated = "Unterminated character class";
  static const char* kRangeOutOfOrder = "Range out of order in character class";

  ASSERT_EQ(current(), '[');
  Advance();
  bool is_negated = false;
  if (current() == '^') {
    is_negated = true;
    Advance();
  }
  ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
  while (has_more() && current() != ']') {
    uc16 char_class = 0;
    CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
    if (char_class) {
      CharacterRange::AddClassEscape(char_class, ranges);
      continue;
    }
    if (current() == '-') {
      Advance();
      if (current() == kEndMarker) {
        // If we reach the end we break out of the loop and let the
        // following code report an error.
        break;
      } else if (current() == ']') {
        ranges->Add(first);
        ranges->Add(CharacterRange::Singleton('-'));
        break;
      }
      CharacterRange next = ParseClassAtom(&char_class CHECK_FAILED);
      if (char_class) {
        ranges->Add(first);
        ranges->Add(CharacterRange::Singleton('-'));
        CharacterRange::AddClassEscape(char_class, ranges);
        continue;
      }
      if (first.from() > next.to()) {
        return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
      }
      ranges->Add(CharacterRange::Range(first.from(), next.to()));
    } else {
      ranges->Add(first);
    }
  }
  if (!has_more()) {
    return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
  }
  Advance();
  if (ranges->length() == 0) {
    ranges->Add(CharacterRange::Everything());
    is_negated = !is_negated;
  }
  return new RegExpCharacterClass(ranges, is_negated);
}


// ----------------------------------------------------------------------------
// The Parser interface.

// MakeAST() is just a wrapper for the corresponding Parser calls
// so we don't have to expose the entire Parser class in the .h file.

static bool always_allow_natives_syntax = false;


ParserMessage::~ParserMessage() {
  for (int i = 0; i < args().length(); i++)
    DeleteArray(args()[i]);
  DeleteArray(args().start());
}


ScriptDataImpl::~ScriptDataImpl() {
  store_.Dispose();
}


int ScriptDataImpl::Length() {
  return store_.length();
}


unsigned* ScriptDataImpl::Data() {
  return store_.start();
}


ScriptDataImpl* PreParse(Handle<String> source,
                         unibrow::CharacterStream* stream,
                         v8::Extension* extension) {
  Handle<Script> no_script;
  bool allow_natives_syntax =
      always_allow_natives_syntax ||
      FLAG_allow_natives_syntax ||
      Bootstrapper::IsActive();
  PreParser parser(no_script, allow_natives_syntax, extension);
  if (!parser.PreParseProgram(source, stream)) return NULL;
  // The list owns the backing store so we need to clone the vector.
  // That way, the result will be exactly the right size rather than
  // the expected 50% too large.
  Vector<unsigned> store = parser.recorder()->store()->ToVector().Clone();
  return new ScriptDataImpl(store);
}


bool ParseRegExp(FlatStringReader* input,
                 bool multiline,
                 RegExpCompileData* result) {
  ASSERT(result != NULL);
  RegExpParser parser(input, &result->error, multiline);
  RegExpTree* tree = parser.ParsePattern();
  if (parser.failed()) {
    ASSERT(tree == NULL);
    ASSERT(!result->error.is_null());
  } else {
    ASSERT(tree != NULL);
    ASSERT(result->error.is_null());
    result->tree = tree;
    int capture_count = parser.captures_started();
    result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
    result->contains_anchor = parser.contains_anchor();
    result->capture_count = capture_count;
  }
  return !parser.failed();
}


FunctionLiteral* MakeAST(bool compile_in_global_context,
                         Handle<Script> script,
                         v8::Extension* extension,
                         ScriptDataImpl* pre_data) {
  bool allow_natives_syntax =
      always_allow_natives_syntax ||
      FLAG_allow_natives_syntax ||
      Bootstrapper::IsActive();
  AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data);
  if (pre_data != NULL && pre_data->has_error()) {
    Scanner::Location loc = pre_data->MessageLocation();
    const char* message = pre_data->BuildMessage();
    Vector<const char*> args = pre_data->BuildArgs();
    parser.ReportMessageAt(loc, message, args);
    DeleteArray(message);
    for (int i = 0; i < args.length(); i++)
      DeleteArray(args[i]);
    DeleteArray(args.start());
    return NULL;
  }
  Handle<String> source = Handle<String>(String::cast(script->source()));
  SafeStringInputBuffer input(source.location());
  FunctionLiteral* result = parser.ParseProgram(source,
      &input, compile_in_global_context);
  return result;
}


FunctionLiteral* MakeLazyAST(Handle<Script> script,
                             Handle<String> name,
                             int start_position,
                             int end_position,
                             bool is_expression) {
  bool allow_natives_syntax_before = always_allow_natives_syntax;
  always_allow_natives_syntax = true;
  AstBuildingParser parser(script, true, NULL, NULL);  // always allow
  always_allow_natives_syntax = allow_natives_syntax_before;
  // Parse the function by pulling the function source from the script source.
  Handle<String> script_source(String::cast(script->source()));
  FunctionLiteral* result =
      parser.ParseLazy(SubString(script_source, start_position, end_position),
                       name,
                       start_position,
                       is_expression);
  return result;
}


#undef NEW


} }  // namespace v8::internal
