1fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Redistribution and use in source and binary forms, with or without
343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// modification, are permitted provided that the following conditions are
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// met:
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions of source code must retain the above copyright
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       notice, this list of conditions and the following disclaimer.
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions in binary form must reproduce the above
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       copyright notice, this list of conditions and the following
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       disclaimer in the documentation and/or other materials provided
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       with the distribution.
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Neither the name of Google Inc. nor the names of its
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       contributors may be used to endorse or promote products derived
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       from this software without specific prior written permission.
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "v8.h"
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "api.h"
31c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org#include "ast.h"
3243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "bootstrapper.h"
331805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org#include "char-predicates-inl.h"
34f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org#include "codegen.h"
35b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#include "compiler.h"
3665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "func-name-inferrer.h"
37ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org#include "messages.h"
38dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org#include "parser.h"
3943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "platform.h"
40fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org#include "preparser.h"
4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "runtime.h"
4255ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org#include "scanner-character-streams.h"
43b5737496145078e47f3d28f19ed8d918e2254738ager@chromium.org#include "scopeinfo.h"
44a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include "string-stream.h"
4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
4771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
4843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
49b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org// PositionStack is used for on-stack allocation of token positions for
50b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org// new expressions. Please look at ParseNewExpression.
51b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
52b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgclass PositionStack  {
53b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org public:
54b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
55068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org  ~PositionStack() {
56068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org    ASSERT(!*ok_ || is_empty());
57068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org    USE(ok_);
58068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org  }
59b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
60b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  class Element  {
61b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org   public:
62b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    Element(PositionStack* stack, int value) {
63b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org      previous_ = stack->top();
64b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org      value_ = value;
65b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org      stack->set_top(this);
66b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    }
67b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
68b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org   private:
69b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    Element* previous() { return previous_; }
70b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    int value() { return value_; }
71b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    friend class PositionStack;
72b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    Element* previous_;
73b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    int value_;
74b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  };
75b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
76b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  bool is_empty() { return top_ == NULL; }
77b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  int pop() {
78b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    ASSERT(!is_empty());
79b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    int result = top_->value();
80b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    top_ = top_->previous();
81b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    return result;
82b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  }
83b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
84b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org private:
85b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Element* top() { return top_; }
86b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  void set_top(Element* value) { top_ = value; }
87b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Element* top_;
88b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  bool* ok_;
89b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org};
90b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
91b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
92400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.orgRegExpBuilder::RegExpBuilder(Zone* zone)
93400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org    : zone_(zone),
94c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      pending_empty_(false),
95c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      characters_(NULL),
96c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      terms_(),
97c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      alternatives_()
98a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#ifdef DEBUG
99c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    , last_added_(ADD_NONE)
100a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif
101a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  {}
102a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
103a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
104a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::FlushCharacters() {
105a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  pending_empty_ = false;
106a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (characters_ != NULL) {
107c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
108a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    characters_ = NULL;
1097028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    text_.Add(atom, zone());
110a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    LAST(ADD_ATOM);
111a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
112a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
113a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
114a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
115a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::FlushText() {
116a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushCharacters();
117a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int num_text = text_.length();
118a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_text == 0) {
119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
120a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (num_text == 1) {
1217028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    terms_.Add(text_.last(), zone());
122a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
1237028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    RegExpText* text = new(zone()) RegExpText(zone());
124a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    for (int i = 0; i < num_text; i++)
1257028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      text_.Get(i)->AppendToText(text, zone());
1267028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    terms_.Add(text, zone());
127a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
128a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  text_.Clear();
129a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
130a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
131a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
132a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddCharacter(uc16 c) {
133a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  pending_empty_ = false;
134a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (characters_ == NULL) {
1357028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    characters_ = new(zone()) ZoneList<uc16>(4, zone());
136a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
1377028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  characters_->Add(c, zone());
138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_CHAR);
139a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
141a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
142a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddEmpty() {
143a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  pending_empty_ = true;
144a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
145a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
146a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
147a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddAtom(RegExpTree* term) {
148a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (term->IsEmpty()) {
149a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    AddEmpty();
150a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
151a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
152a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (term->IsTextElement()) {
153a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushCharacters();
1547028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    text_.Add(term, zone());
155a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
156a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushText();
1577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    terms_.Add(term, zone());
158a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
159a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_ATOM);
160a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
161a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
162a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
163a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddAssertion(RegExpTree* assert) {
164a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushText();
1657028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  terms_.Add(assert, zone());
166a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_ASSERT);
167a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
168a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
169a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
170a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::NewAlternative() {
171a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushTerms();
172a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
173a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
174a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
175a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::FlushTerms() {
176a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushText();
177a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int num_terms = terms_.length();
178a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  RegExpTree* alternative;
179a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_terms == 0) {
180a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    alternative = RegExpEmpty::GetInstance();
181a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (num_terms == 1) {
182a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    alternative = terms_.last();
183a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
1847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    alternative = new(zone()) RegExpAlternative(terms_.GetList(zone()));
185a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
1867028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  alternatives_.Add(alternative, zone());
187a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  terms_.Clear();
188a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_NONE);
189a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
190a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
191a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
192a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpBuilder::ToRegExp() {
193a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushTerms();
194a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int num_alternatives = alternatives_.length();
195a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_alternatives == 0) {
196a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return RegExpEmpty::GetInstance();
197a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
198a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_alternatives == 1) {
199a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return alternatives_.last();
200a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
2017028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  return new(zone()) RegExpDisjunction(alternatives_.GetList(zone()));
202a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
203a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
204a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
205dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgvoid RegExpBuilder::AddQuantifierToAtom(
206dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    int min, int max, RegExpQuantifier::QuantifierType quantifier_type) {
207a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (pending_empty_) {
208a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    pending_empty_ = false;
209a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
210a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
211a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  RegExpTree* atom;
212a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (characters_ != NULL) {
213a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ASSERT(last_added_ == ADD_CHAR);
214a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Last atom was character.
215a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Vector<const uc16> char_vector = characters_->ToConstVector();
216a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int num_chars = char_vector.length();
217a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (num_chars > 1) {
218a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
2197028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      text_.Add(new(zone()) RegExpAtom(prefix), zone());
220a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      char_vector = char_vector.SubVector(num_chars - 1, num_chars);
221a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
222a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    characters_ = NULL;
223c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    atom = new(zone()) RegExpAtom(char_vector);
224a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushText();
225a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (text_.length() > 0) {
226a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ASSERT(last_added_ == ADD_ATOM);
227a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    atom = text_.RemoveLast();
228a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushText();
229a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (terms_.length() > 0) {
230a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ASSERT(last_added_ == ADD_ATOM);
231a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    atom = terms_.RemoveLast();
23237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (atom->max_match() == 0) {
23337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      // Guaranteed to only match an empty string.
234a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      LAST(ADD_TERM);
235a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (min == 0) {
236a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return;
237a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
2387028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      terms_.Add(atom, zone());
239a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return;
240a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
241a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
242a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Only call immediately after adding an atom or character!
243a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    UNREACHABLE();
244a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
245a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
246dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  terms_.Add(
247dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone());
248a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_TERM);
249a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
250a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
251a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
2529e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.orgHandle<String> Parser::LookupSymbol(int symbol_id) {
253fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  // Length of symbol cache is the number of identified symbols.
254fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  // If we are larger than that, or negative, it's not a cached symbol.
255fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  // This might also happen if there is no preparser symbol data, even
256fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  // if there is some preparser data.
257fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (static_cast<unsigned>(symbol_id)
258fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      >= static_cast<unsigned>(symbol_cache_.length())) {
2599e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    if (scanner().is_literal_ascii()) {
2604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      return isolate()->factory()->InternalizeOneByteString(
26159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org          Vector<const uint8_t>::cast(scanner().literal_ascii_string()));
2629e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    } else {
2634a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      return isolate()->factory()->InternalizeTwoByteString(
264154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org          scanner().literal_utf16_string());
2659e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    }
266fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  }
2679e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  return LookupCachedSymbol(symbol_id);
268fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org}
269fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org
270fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org
2719e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.orgHandle<String> Parser::LookupCachedSymbol(int symbol_id) {
272fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  // Make sure the cache is large enough to hold the symbol identifier.
273fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (symbol_cache_.length() <= symbol_id) {
274fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    // Increase length to index + 1.
275fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    symbol_cache_.AddBlock(Handle<String>::null(),
2767028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                           symbol_id + 1 - symbol_cache_.length(), zone());
277fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  }
278fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  Handle<String> result = symbol_cache_.at(symbol_id);
279fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (result.is_null()) {
2809e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    if (scanner().is_literal_ascii()) {
2814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      result = isolate()->factory()->InternalizeOneByteString(
28259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org          Vector<const uint8_t>::cast(scanner().literal_ascii_string()));
2839e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    } else {
2844a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      result = isolate()->factory()->InternalizeTwoByteString(
285154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org          scanner().literal_utf16_string());
2869e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    }
287fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    symbol_cache_.at(symbol_id) = result;
2885b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    return result;
28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
2907979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  isolate()->counters()->total_preparse_symbols_skipped()->Increment();
291fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  return result;
292fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org}
29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
295d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.orgFunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
296d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // The current pre-data entry must be a FunctionEntry with the given
297d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // start position.
2985b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if ((function_index_ + FunctionEntry::kSize <= store_.length())
2995b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org      && (static_cast<int>(store_[function_index_]) == start)) {
3005b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    int index = function_index_;
3015b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    function_index_ += FunctionEntry::kSize;
302d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    return FunctionEntry(store_.SubVector(index,
303d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                                          index + FunctionEntry::kSize));
30443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
30543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return FunctionEntry();
30643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
30743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
30843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
309d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.comint ScriptDataImpl::GetSymbolIdentifier() {
310d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  return ReadNumber(&symbol_data_);
3115b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org}
3125b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org
3135b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org
3145b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.orgbool ScriptDataImpl::SanityCheck() {
3155b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  // Check that the header data is valid and doesn't specify
3165b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  // point to positions outside the store.
317beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
318beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  if (magic() != PreparseDataConstants::kMagicNumber) return false;
319beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  if (version() != PreparseDataConstants::kCurrentVersion) return false;
3205b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (has_error()) {
3215b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    // Extra sane sanity check for error message encoding.
322beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    if (store_.length() <= PreparseDataConstants::kHeaderSize
323beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org                         + PreparseDataConstants::kMessageTextPos) {
324beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      return false;
325beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    }
326beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    if (Read(PreparseDataConstants::kMessageStartPos) >
327beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org        Read(PreparseDataConstants::kMessageEndPos)) {
328beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      return false;
329beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    }
330beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
331beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    int pos = PreparseDataConstants::kMessageTextPos;
3325b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    for (unsigned int i = 0; i <= arg_count; i++) {
333beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
334beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org        return false;
335beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      }
3365b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org      int length = static_cast<int>(Read(pos));
3375b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org      if (length < 0) return false;
3385b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org      pos += 1 + length;
3395b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    }
340beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
341beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      return false;
342beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    }
3435b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    return true;
3445b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  }
3455b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  // Check that the space allocated for function entries is sane.
3465b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  int functions_size =
347beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
3485b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (functions_size < 0) return false;
3495b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (functions_size % FunctionEntry::kSize != 0) return false;
3505b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  // Check that the count of symbols is non-negative.
3515b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  int symbol_count =
352beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
3535b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (symbol_count < 0) return false;
354d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Check that the total size has room for header and function entries.
3555b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  int minimum_size =
356beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      PreparseDataConstants::kHeaderSize + functions_size;
3575b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (store_.length() < minimum_size) return false;
35843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return true;
35943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
36043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
36143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3622ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
36365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgconst char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
36443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int length = start[0];
36543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char* result = NewArray<char>(length + 1);
36665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  for (int i = 0; i < length; i++) {
36743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    result[i] = start[i + 1];
36865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
36943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  result[length] = '\0';
37043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (chars != NULL) *chars = length;
37143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
37243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
37343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
374e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
37543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenScanner::Location ScriptDataImpl::MessageLocation() {
376beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
377beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  int end_pos = Read(PreparseDataConstants::kMessageEndPos);
37843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return Scanner::Location(beg_pos, end_pos);
37943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
38043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
38143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
38243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* ScriptDataImpl::BuildMessage() {
383beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
38465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  return ReadString(start, NULL);
38543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
38643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
38743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
38843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenVector<const char*> ScriptDataImpl::BuildArgs() {
389beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
39043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char** array = NewArray<const char*>(arg_count);
391d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Position after text found by skipping past length field and
392d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // length field content words.
393beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  int pos = PreparseDataConstants::kMessageTextPos + 1
394beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      + Read(PreparseDataConstants::kMessageTextPos);
39543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (int i = 0; i < arg_count; i++) {
39643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    int count = 0;
39765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    array[i] = ReadString(ReadAddress(pos), &count);
39843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    pos += count + 1;
39943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
40043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return Vector<const char*>(array, arg_count);
40143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
40243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
40343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
40443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenunsigned ScriptDataImpl::Read(int position) {
405beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  return store_[PreparseDataConstants::kHeaderSize + position];
40643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
40743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
40843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
40943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenunsigned* ScriptDataImpl::ReadAddress(int position) {
410beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  return &store_[PreparseDataConstants::kHeaderSize + position];
41143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
41243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
41343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
414dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgScope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
415dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  Scope* result = new(zone()) Scope(parent, scope_type, zone());
416394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  result->Initialize();
41743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
41843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
41943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4204f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
42143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
42243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Target is a support class to facilitate manipulation of the
42343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Parser's target_stack_ (the stack of potential 'break' and
42443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 'continue' statement targets). Upon construction, a new target is
42543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// added; it is removed upon destruction.
42643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
42743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass Target BASE_EMBEDDED {
42843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
429e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target(Target** variable, AstNode* node)
430e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org      : variable_(variable), node_(node), previous_(*variable) {
431e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable = this;
43243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
43343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
43443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ~Target() {
435e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable_ = previous_;
43643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
43743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
438b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Target* previous() { return previous_; }
4390b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  AstNode* node() { return node_; }
440b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
44143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
442e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target** variable_;
4430b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  AstNode* node_;
444b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Target* previous_;
44543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
44643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
44743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
44843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass TargetScope BASE_EMBEDDED {
44943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
450e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  explicit TargetScope(Target** variable)
451e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org      : variable_(variable), previous_(*variable) {
452e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable = NULL;
45343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
45443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
45543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ~TargetScope() {
456e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable_ = previous_;
45743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
45843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
45943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
460e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target** variable_;
461b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Target* previous_;
46243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
46343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
46443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
46543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
466c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org// FunctionState and BlockState together implement the parser's scope stack.
467c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org// The parser's current scope is in top_scope_.  The BlockState and
468c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org// FunctionState constructors push on the scope stack and the destructors
469c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org// pop.  They are also used to hold the parser's per-function and per-block
470c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org// state.
471394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
472c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.orgclass Parser::BlockState BASE_EMBEDDED {
473394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com public:
474c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  BlockState(Parser* parser, Scope* scope)
475394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      : parser_(parser),
476c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        outer_scope_(parser->top_scope_) {
477394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    parser->top_scope_ = scope;
478394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
479394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
480c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  ~BlockState() { parser_->top_scope_ = outer_scope_; }
481394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
482394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com private:
483394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Parser* parser_;
484c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  Scope* outer_scope_;
485394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com};
486394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
48743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
488c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.orgParser::FunctionState::FunctionState(Parser* parser,
489c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org                                     Scope* scope,
490c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org                                     Isolate* isolate)
491c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
49204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org      next_handler_index_(0),
493c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      expected_property_count_(0),
494e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      generator_object_variable_(NULL),
495c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      parser_(parser),
496c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      outer_function_state_(parser->current_function_state_),
497c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      outer_scope_(parser->top_scope_),
498b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      saved_ast_node_id_(isolate->ast_node_id()),
4995a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      factory_(isolate, parser->zone()) {
500ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  parser->top_scope_ = scope;
501c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  parser->current_function_state_ = this;
502471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  isolate->set_ast_node_id(BailoutId::FirstUsable().ToInt());
503ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
504ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
505ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
506c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.orgParser::FunctionState::~FunctionState() {
507c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  parser_->top_scope_ = outer_scope_;
508c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  parser_->current_function_state_ = outer_function_state_;
50956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  if (outer_function_state_ != NULL) {
51056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    parser_->isolate()->set_ast_node_id(saved_ast_node_id_);
51156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  }
512ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
513ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
514ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
51543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
51643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The CHECK_OK macro is a convenient macro to enforce error
51743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// handling for functions that may fail (by returning !*ok).
51843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
51943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// CAUTION: This macro appends extra statements after a call,
52043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// thus it must never be used where only a single statement
52143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// is correct (e.g. an if statement branch w/o braces)!
52243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
52343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define CHECK_OK  ok);   \
52443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (!*ok) return NULL; \
52543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ((void)0
52643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define DUMMY )  // to make indentation work
52743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#undef DUMMY
52843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
529a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_FAILED  /**/);   \
530a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (failed_) return NULL; \
531a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ((void)0
532a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DUMMY )  // to make indentation work
533a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef DUMMY
53443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
53543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
53643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Implementation of Parser
53743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
538e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgParser::Parser(CompilationInfo* info)
539a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    : ParserBase(&scanner_, info->isolate()->stack_guard()->real_climit()),
540a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      isolate_(info->isolate()),
541e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      symbol_cache_(0, info->zone()),
5425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      script_(info->script()),
543a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      scanner_(isolate_->unicode_cache()),
5441b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      reusable_preparser_(NULL),
54543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      top_scope_(NULL),
5461e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      original_scope_(NULL),
547c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      current_function_state_(NULL),
54843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      target_stack_(NULL),
549e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      extension_(info->extension()),
550e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      pre_parse_data_(NULL),
551a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      fni_(NULL),
552400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      parenthesized_function_(false),
5535a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      zone_(info->zone()),
5545a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      info_(info) {
5555a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  ASSERT(!script_.is_null());
55656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  isolate_->set_ast_node_id(0);
557e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
558e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_modules(!info->is_native() && FLAG_harmony_modules);
559e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
560e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_lazy(false);  // Must be explicitly enabled.
561e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_generators(FLAG_harmony_generators);
5621fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  set_allow_for_of(FLAG_harmony_iteration);
563ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
56443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
56543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
56643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5675a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgFunctionLiteral* Parser::ParseProgram() {
5684000f228dd279f96628ed845f1e81d01ba7e14d8jkummerow@chromium.org  // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
5694000f228dd279f96628ed845f1e81d01ba7e14d8jkummerow@chromium.org  // see comment for HistogramTimerScope class.
5704000f228dd279f96628ed845f1e81d01ba7e14d8jkummerow@chromium.org  HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
57127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  Handle<String> source(String::cast(script_->source()));
5727979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  isolate()->counters()->total_parse_size()->Increment(source->length());
573dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  ElapsedTimer timer;
574dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (FLAG_trace_parse) {
575dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    timer.Start();
576dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
5777028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
57843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
57943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Initialize parser state.
580ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  source->TryFlatten();
581304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  FunctionLiteral* result;
5825f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  if (source->IsExternalTwoByteString()) {
5835f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    // Notice that the stream is destroyed at the end of the branch block.
5845f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    // The last line of the blocks can't be moved outside, even though they're
5855f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    // identical calls.
586154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    ExternalTwoByteStringUtf16CharacterStream stream(
5875f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org        Handle<ExternalTwoByteString>::cast(source), 0, source->length());
5889e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    scanner_.Initialize(&stream);
5891510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    result = DoParseProgram(info(), source);
5905f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  } else {
591154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    GenericStringUtf16CharacterStream stream(source, 0, source->length());
5929e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    scanner_.Initialize(&stream);
5931510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    result = DoParseProgram(info(), source);
5945f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
595304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
596304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  if (FLAG_trace_parse && result != NULL) {
597dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    double ms = timer.Elapsed().InMillisecondsF();
598304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    if (info()->is_eval()) {
599304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      PrintF("[parsing eval");
600304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    } else if (info()->script()->name()->IsString()) {
601304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      String* name = String::cast(info()->script()->name());
602304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      SmartArrayPointer<char> name_chars = name->ToCString();
603304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      PrintF("[parsing script: %s", *name_chars);
604304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    } else {
605304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      PrintF("[parsing script");
606304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    }
607304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    PrintF(" - took %0.3f ms]\n", ms);
608304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  }
609304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  return result;
6105f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org}
6115f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
6125f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
61327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.orgFunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
6141510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                                        Handle<String> source) {
615394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(top_scope_ == NULL);
61643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(target_stack_ == NULL);
617e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (pre_parse_data_ != NULL) pre_parse_data_->Initialize();
61843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
6194a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Handle<String> no_name = isolate()->factory()->empty_string();
62043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
62143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  FunctionLiteral* result = NULL;
62227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
62327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    info->SetGlobalScope(scope);
624355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    if (!info->context().is_null()) {
625355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
626355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    }
6271e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    original_scope_ = scope;
6282c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    if (info->is_eval()) {
6292c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org      if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
6302c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org        scope = NewScope(scope, EVAL_SCOPE);
6312c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org      }
632355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    } else if (info->is_global()) {
633355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      scope = NewScope(scope, GLOBAL_SCOPE);
63427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    }
635394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    scope->set_start_position(0);
636394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    scope->set_end_position(source->length());
637355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
638cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org    // Compute the parsing mode.
639e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY;
640e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (allow_natives_syntax() ||
641e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        extension_ != NULL ||
642e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        scope->is_eval_scope()) {
643cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org      mode = PARSE_EAGERLY;
644cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org    }
645cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org    ParsingModeScope parsing_mode(this, mode);
646cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org
647f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    // Enters 'scope'.
648e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    FunctionState function_state(this, scope, isolate());
649f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org
6501b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    top_scope_->SetLanguageMode(info->language_mode());
6517028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
65243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    bool ok = true;
653a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int beg_pos = scanner().location().beg_pos;
65433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
6551b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (ok && !top_scope_->is_classic_mode()) {
656a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      CheckOctalLiteral(beg_pos, scanner().location().end_pos, &ok);
6570ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    }
6581805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
6591b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (ok && is_extended_mode()) {
6602c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org      CheckConflictingVarDeclarations(top_scope_, &ok);
6611805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    }
6621805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
6639faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
6649faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      if (body->length() != 1 ||
6659faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org          !body->at(0)->IsExpressionStatement() ||
6669faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org          !body->at(0)->AsExpressionStatement()->
6679faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org              expression()->IsFunctionLiteral()) {
668f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org        ReportMessage("single_function_literal", Vector<const char*>::empty());
6699faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        ok = false;
6709faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      }
6719faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    }
6729faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
67343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (ok) {
674b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      result = factory()->NewFunctionLiteral(
675911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org          no_name,
676911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org          top_scope_,
677fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org          body,
678c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          function_state.materialized_literal_count(),
679c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          function_state.expected_property_count(),
68004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org          function_state.handler_count(),
681911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org          0,
68256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org          FunctionLiteral::kNoDuplicateParameters,
6837c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org          FunctionLiteral::ANONYMOUS_EXPRESSION,
684471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org          FunctionLiteral::kGlobalOrEval,
685f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org          FunctionLiteral::kNotParenthesized,
686a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          FunctionLiteral::kNotGenerator,
687a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          0);
688b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      result->set_ast_properties(factory()->visitor()->ast_properties());
6892c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org      result->set_dont_optimize_reason(
6902c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org          factory()->visitor()->dont_optimize_reason());
691a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    } else if (stack_overflow()) {
692ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      isolate()->StackOverflow();
69343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
69443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
69543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
69643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make sure the target stack is empty.
69743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(target_stack_ == NULL);
69843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
69943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
70043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
70143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
702f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
7035a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgFunctionLiteral* Parser::ParseLazy() {
704dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
705f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org  Handle<String> source(String::cast(script_->source()));
7067979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  isolate()->counters()->total_parse_size()->Increment(source->length());
707dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  ElapsedTimer timer;
708dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (FLAG_trace_parse) {
709dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    timer.Start();
710dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
7115a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
712304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
7135f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Initialize parser state.
7145f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  source->TryFlatten();
715304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  FunctionLiteral* result;
7165f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  if (source->IsExternalTwoByteString()) {
717154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    ExternalTwoByteStringUtf16CharacterStream stream(
7185f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org        Handle<ExternalTwoByteString>::cast(source),
7194d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org        shared_info->start_position(),
7204d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org        shared_info->end_position());
7211510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    result = ParseLazy(&stream);
7225f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  } else {
723154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    GenericStringUtf16CharacterStream stream(source,
724154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org                                             shared_info->start_position(),
725154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org                                             shared_info->end_position());
7261510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    result = ParseLazy(&stream);
7275f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
728304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
729304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  if (FLAG_trace_parse && result != NULL) {
730dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    double ms = timer.Elapsed().InMillisecondsF();
731de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org    SmartArrayPointer<char> name_chars = result->debug_name()->ToCString();
732304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    PrintF("[parsing function: %s - took %0.3f ms]\n", *name_chars, ms);
733304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  }
734304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  return result;
7355f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org}
7365f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
7375f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
7381510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgFunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
7395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
7409e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  scanner_.Initialize(source);
741394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(top_scope_ == NULL);
7425f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  ASSERT(target_stack_ == NULL);
7435f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
7444d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org  Handle<String> name(String::cast(shared_info->name()));
7457028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
74665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  fni_->PushEnclosingName(name);
74765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
748471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
74943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
75043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Place holder for the result.
75143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  FunctionLiteral* result = NULL;
75243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
75343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {
75443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Parse the function literal.
755394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
7565a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    info()->SetGlobalScope(scope);
7575a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    if (!info()->closure().is_null()) {
7585a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
7597028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                           zone());
7604d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    }
7611e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    original_scope_ = scope;
762e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    FunctionState function_state(this, scope, isolate());
7635a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
7641b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    ASSERT(scope->language_mode() != EXTENDED_MODE ||
7655a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org           info()->is_extended_mode());
7665a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    ASSERT(info()->language_mode() == shared_info->language_mode());
7671b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    scope->SetLanguageMode(shared_info->language_mode());
768dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    FunctionLiteral::FunctionType function_type = shared_info->is_expression()
7697c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org        ? (shared_info->is_anonymous()
7707c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org              ? FunctionLiteral::ANONYMOUS_EXPRESSION
7717c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org              : FunctionLiteral::NAMED_EXPRESSION)
7727c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org        : FunctionLiteral::DECLARATION;
77343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    bool ok = true;
77483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    result = ParseFunctionLiteral(name,
7757c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                  false,  // Strict mode name already checked.
776f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                                  shared_info->is_generator(),
7777c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                  RelocInfo::kNoPosition,
778dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                                  function_type,
7797c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                  &ok);
78043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Make sure the results agree.
78143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ASSERT(ok == (result != NULL));
78243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
78343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
78443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make sure the target stack is empty.
78543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(target_stack_ == NULL);
78643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
78743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (result == NULL) {
788a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    if (stack_overflow()) isolate()->StackOverflow();
789a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  } else {
7904d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    Handle<String> inferred_name(shared_info->inferred_name());
791a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    result->set_inferred_name(inferred_name);
79243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
79343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
79443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
79543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
796f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
797bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.orgHandle<String> Parser::GetSymbol() {
798d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  int symbol_id = -1;
799e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (pre_parse_data() != NULL) {
800e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    symbol_id = pre_parse_data()->GetSymbolIdentifier();
8015b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  }
8029e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  return LookupSymbol(symbol_id);
8035b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org}
8045b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org
8055b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org
806dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgvoid Parser::ReportMessage(const char* message, Vector<const char*> args) {
8075f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Scanner::Location source_location = scanner().location();
808dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  ReportMessageAt(source_location, message, args);
809fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org}
810fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org
811fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org
812dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgvoid Parser::ReportMessage(const char* message, Vector<Handle<String> > args) {
813bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  Scanner::Location source_location = scanner().location();
814dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  ReportMessageAt(source_location, message, args);
815bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com}
816bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
817bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
818fa943b736b1d996084393011529d568165bb5d83lrn@chromium.orgvoid Parser::ReportMessageAt(Scanner::Location source_location,
819dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                             const char* message,
820fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org                             Vector<const char*> args) {
82143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  MessageLocation location(script_,
822c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           source_location.beg_pos,
823c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           source_location.end_pos);
824ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Factory* factory = isolate()->factory();
825ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
82643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (int i = 0; i < args.length(); i++) {
827ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
8288f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    elements->set(i, *arg_string);
82943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
830ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
831dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  Handle<Object> result = factory->NewSyntaxError(message, array);
832ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate()->Throw(*result, &location);
83343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
83443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
83543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
836c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.orgvoid Parser::ReportMessageAt(Scanner::Location source_location,
837dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                             const char* message,
838c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                             Vector<Handle<String> > args) {
839c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  MessageLocation location(script_,
840c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           source_location.beg_pos,
841c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           source_location.end_pos);
842ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Factory* factory = isolate()->factory();
843ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
844c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  for (int i = 0; i < args.length(); i++) {
8458f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    elements->set(i, *args[i]);
846c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  }
847ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
848dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  Handle<Object> result = factory->NewSyntaxError(message, array);
849ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate()->Throw(*result, &location);
850c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org}
851c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
852c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
853fa943b736b1d996084393011529d568165bb5d83lrn@chromium.orgvoid* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
85443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                  int end_token,
8552c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org                                  bool is_eval,
85633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org                                  bool is_global,
85743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                  bool* ok) {
85843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // SourceElements ::
859f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //   (ModuleElement)* <end_token>
86043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
86143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Allocate a target stack to use for this set of source
86243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // elements. This way, all scripts and functions get their own
86343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // target stack thus avoiding illegal breaks and continues across
86443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // functions.
865e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  TargetScope scope(&this->target_stack_);
86643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
86743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(processor != NULL);
8680a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  bool directive_prologue = true;     // Parsing directive prologue.
8690a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
87043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != end_token) {
8710a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (directive_prologue && peek() != Token::STRING) {
8720a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      directive_prologue = false;
8730a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
8740a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
8750a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    Scanner::Location token_loc = scanner().peek_location();
87633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    Statement* stat;
87733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    if (is_global && !is_eval) {
87833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      stat = ParseModuleElement(NULL, CHECK_OK);
87933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    } else {
88033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      stat = ParseBlockElement(NULL, CHECK_OK);
88133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    }
8820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (stat == NULL || stat->IsEmpty()) {
8830a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      directive_prologue = false;   // End of directive prologue.
8840a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      continue;
8850a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
8860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
8870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (directive_prologue) {
8880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      // A shot at a directive.
889f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      ExpressionStatement* e_stat;
890f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      Literal* literal;
8910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      // Still processing directive prologue?
8920a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      if ((e_stat = stat->AsExpressionStatement()) != NULL &&
8930a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org          (literal = e_stat->expression()->AsLiteral()) != NULL &&
8941510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org          literal->value()->IsString()) {
8951510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        Handle<String> directive = Handle<String>::cast(literal->value());
8960a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
8970a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        // Check "use strict" directive (ES5 14.1).
8981b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        if (top_scope_->is_classic_mode() &&
8994a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org            directive->Equals(isolate()->heap()->use_strict_string()) &&
9000a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org            token_loc.end_pos - token_loc.beg_pos ==
9014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org              isolate()->heap()->use_strict_string()->length() + 2) {
9022c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // TODO(mstarzinger): Global strict eval calls, need their own scope
9032c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // as specified in ES5 10.4.2(3). The correct fix would be to always
9042c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // add this scope in DoParseProgram(), but that requires adaptations
9052c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // all over the code base, so we go with a quick-fix for now.
906cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org          // In the same manner, we have to patch the parsing mode.
9072c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          if (is_eval && !top_scope_->is_eval_scope()) {
9082c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org            ASSERT(top_scope_->is_global_scope());
9092c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org            Scope* scope = NewScope(top_scope_, EVAL_SCOPE);
9102c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org            scope->set_start_position(top_scope_->start_position());
9112c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org            scope->set_end_position(top_scope_->end_position());
9122c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org            top_scope_ = scope;
913cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org            mode_ = PARSE_EAGERLY;
9142c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          }
9151b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          // TODO(ES6): Fix entering extended mode, once it is specified.
916e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org          top_scope_->SetLanguageMode(allow_harmony_scoping()
9171b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                                      ? EXTENDED_MODE : STRICT_MODE);
9180a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org          // "use strict" is the only directive for now.
9190a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org          directive_prologue = false;
9200a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        }
9210a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      } else {
9220a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        // End of the directive prologue.
9230a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        directive_prologue = false;
9240a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      }
9250a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
9260a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
9277028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    processor->Add(stat, zone());
92843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
929911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
93043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return 0;
93143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
93243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
93343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
934f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgStatement* Parser::ParseModuleElement(ZoneStringList* labels,
935f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org                                      bool* ok) {
936f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // (Ecma 262 5th Edition, clause 14):
937f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // SourceElement:
938f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Statement
939f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    FunctionDeclaration
940f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //
941f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // In harmony mode we allow additionally the following productions
942f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModuleElement:
943f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    LetDeclaration
944f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ConstDeclaration
945f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ModuleDeclaration
946f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ImportDeclaration
947f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ExportDeclaration
948f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //    GeneratorDeclaration
949f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
950f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  switch (peek()) {
951f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::FUNCTION:
952812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseFunctionDeclaration(NULL, ok);
953f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::LET:
954f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::CONST:
955812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseVariableStatement(kModuleElement, NULL, ok);
956f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::IMPORT:
957f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseImportDeclaration(ok);
958f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::EXPORT:
959f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseExportDeclaration(ok);
960a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org    default: {
961a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      Statement* stmt = ParseStatement(labels, CHECK_OK);
962a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      // Handle 'module' as a context-sensitive keyword.
963a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      if (FLAG_harmony_modules &&
964a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org          peek() == Token::IDENTIFIER &&
965a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org          !scanner().HasAnyLineTerminatorBeforeNext() &&
966a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org          stmt != NULL) {
967a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org        ExpressionStatement* estmt = stmt->AsExpressionStatement();
968a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org        if (estmt != NULL &&
969a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org            estmt->expression()->AsVariableProxy() != NULL &&
970a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org            estmt->expression()->AsVariableProxy()->name()->Equals(
9714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                isolate()->heap()->module_string()) &&
972a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org            !scanner().literal_contains_escapes()) {
973812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org          return ParseModuleDeclaration(NULL, ok);
974a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org        }
975a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      }
976a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      return stmt;
977a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org    }
978f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
979f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
980f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
981f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
98281cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.orgStatement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
983f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModuleDeclaration:
984f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    'module' Identifier Module
985f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
986a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
987f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Handle<String> name = ParseIdentifier(CHECK_OK);
988bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
989bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
990bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details)
991bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    PrintF("# Module %s...\n", name->ToAsciiArray());
992bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
993bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
994812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Module* module = ParseModule(CHECK_OK);
9958e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
996812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declaration* declaration =
997a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewModuleDeclaration(proxy, module, top_scope_, pos);
998812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declare(declaration, true, CHECK_OK);
999812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1000bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1001bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details)
1002bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    PrintF("# Module %s.\n", name->ToAsciiArray());
1003bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1004bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interfaces) {
1005bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    PrintF("module %s : ", name->ToAsciiArray());
1006bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    module->interface()->Print();
1007bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  }
1008bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1009bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
10107028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  if (names) names->Add(name, zone());
101181cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  if (module->body() == NULL)
1012a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewEmptyStatement(pos);
101381cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  else
1014a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewModuleStatement(proxy, module->body(), pos);
1015f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1016f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1017f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1018f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModule(bool* ok) {
1019f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Module:
1020f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    '{' ModuleElement '}'
1021812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    '=' ModulePath ';'
1022812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'at' String ';'
1023f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1024f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  switch (peek()) {
1025f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::LBRACE:
1026f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseModuleLiteral(ok);
1027f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1028812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::ASSIGN: {
1029f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      Expect(Token::ASSIGN, CHECK_OK);
1030812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      Module* result = ParseModulePath(CHECK_OK);
1031812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      ExpectSemicolon(CHECK_OK);
1032812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return result;
1033812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
1034f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1035812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    default: {
10361fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ExpectContextualKeyword(CStrVector("at"), CHECK_OK);
1037812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      Module* result = ParseModuleUrl(CHECK_OK);
1038812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      ExpectSemicolon(CHECK_OK);
1039812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return result;
1040812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
1041f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1042f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1043f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1044f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1045f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModuleLiteral(bool* ok) {
1046f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Module:
1047f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    '{' ModuleElement '}'
1048f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1049a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1050f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Construct block expecting 16 statements.
1051a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* body = factory()->NewBlock(NULL, 16, false, RelocInfo::kNoPosition);
1052bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1053bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details) PrintF("# Literal ");
1054bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1055f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
1056f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1057f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Expect(Token::LBRACE, CHECK_OK);
1058f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  scope->set_start_position(scanner().location().beg_pos);
1059f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  scope->SetLanguageMode(EXTENDED_MODE);
1060f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1061f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  {
1062f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    BlockState block_state(this, scope);
10637028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    TargetCollector collector(zone());
1064f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    Target target(&this->target_stack_, &collector);
1065f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    Target target_body(&this->target_stack_, body);
1066f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1067f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    while (peek() != Token::RBRACE) {
1068f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      Statement* stat = ParseModuleElement(NULL, CHECK_OK);
1069f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      if (stat && !stat->IsEmpty()) {
1070400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body->AddStatement(stat, zone());
1071f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      }
1072f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    }
1073f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1074f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1075f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Expect(Token::RBRACE, CHECK_OK);
1076f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  scope->set_end_position(scanner().location().end_pos);
1077ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  body->set_scope(scope);
1078bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
107981cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  // Check that all exports are bound.
1080ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  Interface* interface = scope->interface();
108181cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  for (Interface::Iterator it = interface->iterator();
108281cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org       !it.done(); it.Advance()) {
108381cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org    if (scope->LocalLookup(it.name()) == NULL) {
108481cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org      Handle<String> name(it.name());
108581cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org      ReportMessage("module_export_undefined",
108681cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org                    Vector<Handle<String> >(&name, 1));
108781cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org      *ok = false;
108881cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org      return NULL;
108981cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org    }
109081cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  }
109181cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org
1092ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  interface->MakeModule(ok);
109381cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  ASSERT(*ok);
1094ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  interface->Freeze(ok);
109581cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  ASSERT(*ok);
1096a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewModuleLiteral(body, interface, pos);
1097f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1098f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1099f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1100f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModulePath(bool* ok) {
1101f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModulePath:
1102f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Identifier
1103f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ModulePath '.' Identifier
1104f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1105a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1106f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Module* result = ParseModuleVariable(CHECK_OK);
1107f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  while (Check(Token::PERIOD)) {
1108f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    Handle<String> name = ParseIdentifierName(CHECK_OK);
1109bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1110bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_print_interface_details)
1111bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      PrintF("# Path .%s ", name->ToAsciiArray());
1112bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1113a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    Module* member = factory()->NewModulePath(result, name, pos);
11147028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    result->interface()->Add(name, member->interface(), zone(), ok);
1115bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (!*ok) {
1116bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1117bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (FLAG_print_interfaces) {
1118bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray());
1119bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("result: ");
1120bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        result->interface()->Print();
1121bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("member: ");
1122bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        member->interface()->Print();
1123bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      }
1124bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1125bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
1126bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      return NULL;
1127bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    }
1128bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    result = member;
1129f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1130f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1131f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  return result;
1132f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1133f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1134f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1135f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModuleVariable(bool* ok) {
1136f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModulePath:
1137f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Identifier
1138f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1139a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1140f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Handle<String> name = ParseIdentifier(CHECK_OK);
1141bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1142bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details)
1143bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    PrintF("# Module variable %s ", name->ToAsciiArray());
1144bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1145f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  VariableProxy* proxy = top_scope_->NewUnresolved(
114628583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org      factory(), name, Interface::NewModule(zone()),
114728583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org      scanner().location().beg_pos);
1148bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1149a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewModuleVariable(proxy, pos);
1150f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1151f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1152f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1153f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModuleUrl(bool* ok) {
1154f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Module:
1155812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    String
1156f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1157a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1158f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Expect(Token::STRING, CHECK_OK);
1159bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  Handle<String> symbol = GetSymbol();
1160f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1161bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  // TODO(ES6): Request JS resource from environment...
1162bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1163bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1164bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details) PrintF("# Url ");
1165bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1166ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
11678e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Create an empty literal as long as the feature isn't finished.
11688e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  USE(symbol);
11698e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
1170a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
11718e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  body->set_scope(scope);
11728e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  Interface* interface = scope->interface();
1173a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Module* result = factory()->NewModuleLiteral(body, interface, pos);
1174ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  interface->Freeze(ok);
117581cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  ASSERT(*ok);
117681cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  interface->Unify(scope->interface(), zone(), ok);
117781cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  ASSERT(*ok);
1178ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  return result;
1179f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1180f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1181f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1182812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.orgModule* Parser::ParseModuleSpecifier(bool* ok) {
1183812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // ModuleSpecifier:
1184812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    String
1185812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    ModulePath
1186812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1187812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  if (peek() == Token::STRING) {
1188812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    return ParseModuleUrl(ok);
1189812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  } else {
1190812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    return ParseModulePath(ok);
1191812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1192812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org}
1193812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1194812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1195f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgBlock* Parser::ParseImportDeclaration(bool* ok) {
1196812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // ImportDeclaration:
1197812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';'
1198812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //
1199812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // TODO(ES6): implement destructuring ImportSpecifiers
1200812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1201a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1202812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Expect(Token::IMPORT, CHECK_OK);
12037028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneStringList names(1, zone());
1204812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1205812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Handle<String> name = ParseIdentifierName(CHECK_OK);
12067028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  names.Add(name, zone());
1207812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  while (peek() == Token::COMMA) {
1208812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Consume(Token::COMMA);
1209812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    name = ParseIdentifierName(CHECK_OK);
12107028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    names.Add(name, zone());
1211812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1212812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
12131fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1214812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Module* module = ParseModuleSpecifier(CHECK_OK);
1215812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ExpectSemicolon(CHECK_OK);
1216812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1217812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // Generate a separate declaration for each identifier.
1218812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // TODO(ES6): once we implement destructuring, make that one declaration.
1219a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
1220812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  for (int i = 0; i < names.length(); ++i) {
1221bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1222bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_print_interface_details)
1223bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      PrintF("# Import %s ", names[i]->ToAsciiArray());
1224bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
12257028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Interface* interface = Interface::NewUnknown(zone());
12267028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    module->interface()->Add(names[i], interface, zone(), ok);
1227bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (!*ok) {
1228bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1229bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (FLAG_print_interfaces) {
1230bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray());
1231bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("module: ");
1232bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        module->interface()->Print();
1233bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      }
1234bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1235bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
1236bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      return NULL;
1237bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    }
1238bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
1239812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declaration* declaration =
1240a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        factory()->NewImportDeclaration(proxy, module, top_scope_, pos);
1241812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declare(declaration, true, CHECK_OK);
1242812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1243812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1244812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  return block;
1245f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1246f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1247f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1248812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.orgStatement* Parser::ParseExportDeclaration(bool* ok) {
1249812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // ExportDeclaration:
1250812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' Identifier (',' Identifier)* ';'
1251812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' VariableDeclaration
1252812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' FunctionDeclaration
1253f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //    'export' GeneratorDeclaration
1254812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' ModuleDeclaration
1255812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //
1256812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // TODO(ES6): implement structuring ExportSpecifiers
1257812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1258812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Expect(Token::EXPORT, CHECK_OK);
1259812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1260812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Statement* result = NULL;
12617028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneStringList names(1, zone());
1262812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  switch (peek()) {
1263812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::IDENTIFIER: {
1264a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      int pos = position();
1265812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      Handle<String> name = ParseIdentifier(CHECK_OK);
1266812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      // Handle 'module' as a context-sensitive keyword.
126759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
12687028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        names.Add(name, zone());
1269812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        while (peek() == Token::COMMA) {
1270812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org          Consume(Token::COMMA);
1271812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org          name = ParseIdentifier(CHECK_OK);
12727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          names.Add(name, zone());
1273812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        }
1274812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        ExpectSemicolon(CHECK_OK);
1275a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        result = factory()->NewEmptyStatement(pos);
1276812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      } else {
1277812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        result = ParseModuleDeclaration(&names, CHECK_OK);
1278812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      }
1279812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      break;
1280812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
1281812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1282812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::FUNCTION:
1283812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      result = ParseFunctionDeclaration(&names, CHECK_OK);
1284812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      break;
1285812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1286812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::VAR:
1287812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::LET:
1288812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::CONST:
1289812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      result = ParseVariableStatement(kModuleElement, &names, CHECK_OK);
1290812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      break;
1291812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1292812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    default:
1293812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      *ok = false;
1294812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      ReportUnexpectedToken(scanner().current_token());
1295812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return NULL;
1296812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1297812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1298bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  // Extract declared names into export declarations and interface.
1299bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  Interface* interface = top_scope_->interface();
1300812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  for (int i = 0; i < names.length(); ++i) {
1301bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1302bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_print_interface_details)
1303bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      PrintF("# Export %s ", names[i]->ToAsciiArray());
1304bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
13057028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Interface* inner = Interface::NewUnknown(zone());
13067028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    interface->Add(names[i], inner, zone(), CHECK_OK);
13077028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (!*ok)
13087028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      return NULL;
1309bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    VariableProxy* proxy = NewUnresolved(names[i], LET, inner);
1310bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    USE(proxy);
1311bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    // TODO(rossberg): Rethink whether we actually need to store export
1312bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    // declarations (for compilation?).
1313bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    // ExportDeclaration* declaration =
1314a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    //     factory()->NewExportDeclaration(proxy, top_scope_, position);
1315bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    // top_scope_->AddDeclaration(declaration);
1316812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1317812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1318812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ASSERT(result != NULL);
1319812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  return result;
1320f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1321f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1322f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1323f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgStatement* Parser::ParseBlockElement(ZoneStringList* labels,
1324f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org                                     bool* ok) {
1325f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // (Ecma 262 5th Edition, clause 14):
1326f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // SourceElement:
1327f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Statement
1328f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    FunctionDeclaration
1329f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //
1330f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // In harmony mode we allow additionally the following productions
1331f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // BlockElement (aka SourceElement):
1332f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    LetDeclaration
1333f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ConstDeclaration
1334f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //    GeneratorDeclaration
1335f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1336f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  switch (peek()) {
1337f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::FUNCTION:
1338812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseFunctionDeclaration(NULL, ok);
1339f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::LET:
1340f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::CONST:
1341812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseVariableStatement(kModuleElement, NULL, ok);
1342f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    default:
1343f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseStatement(labels, ok);
1344f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1345f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1346f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1347f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
134843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
134943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Statement ::
135043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Block
135143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   VariableStatement
135243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   EmptyStatement
135343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ExpressionStatement
135443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   IfStatement
135543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   IterationStatement
135643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ContinueStatement
135743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   BreakStatement
135843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ReturnStatement
135943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   WithStatement
136043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   LabelledStatement
136143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   SwitchStatement
136243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ThrowStatement
136343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   TryStatement
136443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   DebuggerStatement
136543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
136643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note: Since labels can only be used by 'break' and 'continue'
136743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // statements, which themselves are only valid within blocks,
136843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // iterations or 'switch' statements (i.e., BreakableStatements),
136943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // labels can be simply ignored in all other cases; except for
13703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // trivial labeled break statements 'label: break label' which is
137143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // parsed into an empty statement.
137243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (peek()) {
137343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::LBRACE:
137443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return ParseBlock(labels, ok);
137543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
137643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::CONST:  // fall through
13771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    case Token::LET:
137843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::VAR:
1379a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseVariableStatement(kStatement, NULL, ok);
138043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
138143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::SEMICOLON:
138243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Next();
1383a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
138443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
138543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::IF:
1386a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseIfStatement(labels, ok);
138743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
138843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::DO:
1389a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseDoWhileStatement(labels, ok);
139043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
139143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::WHILE:
1392a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseWhileStatement(labels, ok);
139343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
139443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::FOR:
1395a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseForStatement(labels, ok);
139643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
139743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::CONTINUE:
1398a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseContinueStatement(ok);
139943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
140043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::BREAK:
1401a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseBreakStatement(labels, ok);
140243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
140343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::RETURN:
1404a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseReturnStatement(ok);
140543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
140643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::WITH:
1407a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseWithStatement(labels, ok);
140843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
140943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::SWITCH:
1410a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseSwitchStatement(labels, ok);
141143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
141243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::THROW:
1413a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseThrowStatement(ok);
141443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
141543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::TRY: {
141643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // NOTE: It is somewhat complicated to have labels on
141743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // try-statements. When breaking out of a try-finally statement,
141843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // one must take great care not to treat it as a
141943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // fall-through. It is much easier just to wrap the entire
142043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // try-statement in a statement block and put the labels there
1421a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      Block* result =
1422a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
1423e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org      Target target(&this->target_stack_, result);
142443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      TryStatement* statement = ParseTryStatement(CHECK_OK);
1425400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      if (result) result->AddStatement(statement, zone());
142643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return result;
142743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
142843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14299ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::FUNCTION: {
1430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // FunctionDeclaration is only allowed in the context of SourceElements
1431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // (Ecma 262 5th Edition, clause 14):
1432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // SourceElement:
1433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      //    Statement
1434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      //    FunctionDeclaration
1435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Common language extension is to allow function declaration in place
1436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // of any statement. This language extension is disabled in strict mode.
1437f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      //
1438f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // In Harmony mode, this case also handles the extension:
1439f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // Statement:
1440f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      //    GeneratorDeclaration
14411b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      if (!top_scope_->is_classic_mode()) {
14429ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        ReportMessageAt(scanner().peek_location(), "strict_function",
14439ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org                        Vector<const char*>::empty());
14449ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        *ok = false;
14459ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        return NULL;
14469ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      }
1447812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseFunctionDeclaration(NULL, ok);
14489ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    }
144943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
145043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::DEBUGGER:
1451a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseDebuggerStatement(ok);
145243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
145343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default:
1454a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseExpressionOrLabelledStatement(labels, ok);
145543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
145643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
145743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
145843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1459bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.comVariableProxy* Parser::NewUnresolved(
1460bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    Handle<String> name, VariableMode mode, Interface* interface) {
1461b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // If we are inside a function, a declaration of a var/const variable is a
1462b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // truly local variable, and the scope of the variable is always the function
1463b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // scope.
1464394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Let/const variables in harmony mode are always added to the immediately
1465394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // enclosing scope.
1466812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  return DeclarationScope(mode)->NewUnresolved(
1467a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory(), name, interface, position());
1468812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org}
1469812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1470812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1471812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.orgvoid Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
1472bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  VariableProxy* proxy = declaration->proxy();
1473bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  Handle<String> name = proxy->name();
1474812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  VariableMode mode = declaration->mode();
1475812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Scope* declaration_scope = DeclarationScope(mode);
1476812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Variable* var = NULL;
147743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
147881cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  // If a suitable scope exists, then we can statically declare this
147943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // variable and also set its mode. In any case, a Declaration node
148043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // will be added to the scope so that the declaration can be added
148143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // to the corresponding activation frame at runtime if necessary.
148243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // For instance declarations inside an eval scope need to be added
148343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // to the calling function context.
14848e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  // Similarly, strict mode eval scope does not leak variable declarations to
14858e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  // the caller's scope so we declare all locals, too.
14864f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (declaration_scope->is_function_scope() ||
14871b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      declaration_scope->is_strict_or_extended_eval_scope() ||
1488f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      declaration_scope->is_block_scope() ||
1489bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      declaration_scope->is_module_scope() ||
1490355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      declaration_scope->is_global_scope()) {
149181cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org    // Declare the variable in the declaration scope.
1492355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    // For the global scope, we have to check for collisions with earlier
1493355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    // (i.e., enclosing) global scopes, to maintain the illusion of a single
1494355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    // global scope.
1495355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    var = declaration_scope->is_global_scope()
1496355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        ? declaration_scope->Lookup(name)
1497355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        : declaration_scope->LocalLookup(name);
149843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (var == NULL) {
149943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // Declare the name.
1500812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      var = declaration_scope->DeclareLocal(
1501bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          name, mode, declaration->initialization(), proxy->interface());
1502355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    } else if ((mode != VAR || var->mode() != VAR) &&
1503355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org               (!declaration_scope->is_global_scope() ||
1504355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org                IsLexicalVariableMode(mode) ||
1505355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org                IsLexicalVariableMode(var->mode()))) {
15061805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // The name was declared in this scope before; check for conflicting
15071805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // re-declarations. We have a conflict if either of the declarations is
1508355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // not a var (in the global scope, we also have to ignore legacy const for
1509355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // compatibility). There is similar code in runtime.cc in the Declare
15101805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // functions. The function CheckNonConflictingScope checks for conflicting
15111805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // var and let bindings from different scopes whereas this is a check for
15121805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // conflicting declarations within the same scope. This check also covers
1513355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // the special case
15141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      //
15151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // function () { let x; { var x; } }
15161805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      //
15171805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // because the var declaration is hoisted to the function scope where 'x'
15181805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // is already bound.
1519355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      ASSERT(IsDeclaredVariableMode(var->mode()));
1520355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      if (is_extended_mode()) {
1521355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        // In harmony mode we treat re-declarations as early errors. See
1522355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        // ES5 16 for a definition of early errors.
1523355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1524355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        const char* elms[2] = { "Variable", *c_string };
1525355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        Vector<const char*> args(elms, 2);
1526355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        ReportMessage("redeclaration", args);
1527355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        *ok = false;
1528355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        return;
152943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
1530dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      Handle<String> message_string =
15318e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org          isolate()->factory()->NewStringFromUtf8(CStrVector("Variable"),
15328e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                                                  TENURED);
1533355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      Expression* expression =
15344a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org          NewThrowTypeError(isolate()->factory()->redeclaration_string(),
1535dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                            message_string, name);
1536355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      declaration_scope->SetIllegalRedeclaration(expression);
153743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
153843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
153943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
154043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // We add a declaration node for every declaration. The compiler
154143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // will only generate code if necessary. In particular, declarations
154243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // for inner local variables that do not represent functions won't
154343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // result in any generated code.
154443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
154543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note that we always add an unresolved proxy even if it's not
154643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // used, simply because we don't know in this method (w/o extra
154743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // parameters) if the proxy is needed or not. The proxy will be
154843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // bound during variable resolution time unless it was pre-bound
154943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // below.
155043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
155143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // WARNING: This will lead to multiple declaration nodes for the
155243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // same variable if it is declared several times. This is not a
155343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // semantic issue as long as we keep the source order, but it may be
155443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // a performance issue since it may lead to repeated
155543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Runtime::DeclareContextSlot() calls.
1556812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  declaration_scope->AddDeclaration(declaration);
155743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1558355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  if (mode == CONST && declaration_scope->is_global_scope()) {
155927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // For global const variables we bind the proxy to a variable.
156043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ASSERT(resolve);  // should be set by all callers
15613e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org    Variable::Kind kind = Variable::NORMAL;
156210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org    var = new(zone()) Variable(
156310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org        declaration_scope, name, mode, true, kind,
156410480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org        kNeedsInitialization, proxy->interface());
156527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  } else if (declaration_scope->is_eval_scope() &&
15661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org             declaration_scope->is_classic_mode()) {
156727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // For variable declarations in a non-strict eval scope the proxy is bound
156827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // to a lookup variable to force a dynamic declaration using the
156927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // DeclareContextSlot runtime function.
157027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    Variable::Kind kind = Variable::NORMAL;
157110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org    var = new(zone()) Variable(
157210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org        declaration_scope, name, mode, true, kind,
157310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org        declaration->initialization(), proxy->interface());
157427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    var->AllocateTo(Variable::LOOKUP, -1);
157527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    resolve = true;
157643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
157743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
157843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // If requested and we have a local variable, bind the proxy to the variable
157943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // at parse-time. This is used for functions (and consts) declared inside
158043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // statements: the corresponding function (or const) variable must be in the
158143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // function scope and not a statement-local scope, e.g. as provided with a
158243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // 'with' statement:
158343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
158443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   with (obj) {
158543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //     function f() {}
158643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   }
158743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
158843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // which is translated into:
158943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
159043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   with (obj) {
159143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //     // in this case this is not: 'var f; f = function () {};'
159243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //     var f = function () {};
159343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   }
159443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
159543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note that if 'f' is accessed from inside the 'with' statement, it
159643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // will be allocated in the context (because we must be able to look
159743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // it up dynamically) but it will also be accessed statically, i.e.,
159843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // with a context slot index and a context chain length for this
159943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // initialization code. Thus, inside the 'with' statement, we need
160043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // both access to the static and the dynamic context chain; the
160143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // runtime needs to provide both.
1602bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (resolve && var != NULL) {
1603bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    proxy->BindTo(var);
1604bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1605bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_harmony_modules) {
1606bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      bool ok;
1607bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1608bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (FLAG_print_interface_details)
1609bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("# Declare %s\n", var->name()->ToAsciiArray());
1610bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
16117028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      proxy->interface()->Unify(var->interface(), zone(), &ok);
1612bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (!ok) {
1613bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1614bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        if (FLAG_print_interfaces) {
1615bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          PrintF("DECLARE TYPE ERROR\n");
1616bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          PrintF("proxy: ");
1617bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          proxy->interface()->Print();
1618bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          PrintF("var: ");
1619bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          var->interface()->Print();
1620bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        }
1621bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1622bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        ReportMessage("module_type_error", Vector<Handle<String> >(&name, 1));
1623bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      }
1624bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    }
1625bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  }
162643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
162743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
162843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
162943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Language extension which is only enabled for source files loaded
163043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// through the API's extension mechanism.  A native function
163143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// declaration is resolved by looking up the function through a
163243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// callback provided by the extension.
163343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseNativeDeclaration(bool* ok) {
1634a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
163543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::FUNCTION, CHECK_OK);
163643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Handle<String> name = ParseIdentifier(CHECK_OK);
163743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
163843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool done = (peek() == Token::RPAREN);
163943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (!done) {
164043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ParseIdentifier(CHECK_OK);
164143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    done = (peek() == Token::RPAREN);
1642fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    if (!done) {
1643fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      Expect(Token::COMMA, CHECK_OK);
1644fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    }
164543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
164643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
164743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SEMICOLON, CHECK_OK);
164843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make sure that the function containing the native declaration
165043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // isn't lazily compiled. The extension structures are only
165143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // accessible while parsing the first time not when reparsing
165243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // because of lazy compilation.
1653812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  DeclarationScope(VAR)->ForceEagerCompilation();
165443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
165543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // TODO(1240846): It's weird that native function declarations are
165643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // introduced dynamically when we meet their declarations, whereas
1657f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // other functions are set up when entering the surrounding scope.
165828583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org  VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
1659812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declaration* declaration =
1660a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewVariableDeclaration(proxy, VAR, top_scope_, pos);
1661812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declare(declaration, true, CHECK_OK);
1662a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
1663a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      name, extension_, RelocInfo::kNoPosition);
1664b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  return factory()->NewExpressionStatement(
1665b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      factory()->NewAssignment(
1666a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition),
1667a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      pos);
166843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
166943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
167043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1671812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.orgStatement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
1672c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // FunctionDeclaration ::
1673c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1674f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  // GeneratorDeclaration ::
1675f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //   'function' '*' Identifier '(' FormalParameterListopt ')'
1676f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //      '{' FunctionBody '}'
167743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::FUNCTION, CHECK_OK);
1678a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
1679e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  bool is_generator = allow_generators() && Check(Token::MUL);
168004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  bool is_strict_reserved = false;
168104921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  Handle<String> name = ParseIdentifierOrStrictReservedWord(
168204921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      &is_strict_reserved, CHECK_OK);
1683c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  FunctionLiteral* fun = ParseFunctionLiteral(name,
168404921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org                                              is_strict_reserved,
1685f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                                              is_generator,
1686a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                              pos,
16877c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                              FunctionLiteral::DECLARATION,
1688c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org                                              CHECK_OK);
1689c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Even if we're not at the top-level of the global or a function
1690355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // scope, we treat it as such and introduce the function with its
1691c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // initial value upon entering the corresponding scope.
1692355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // In extended mode, a function behaves as a lexical binding, except in the
1693355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // global scope.
1694355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  VariableMode mode =
1695355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      is_extended_mode() && !top_scope_->is_global_scope() ? LET : VAR;
169628583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org  VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
1697812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declaration* declaration =
1698a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_, pos);
1699812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declare(declaration, true, CHECK_OK);
17007028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  if (names) names->Add(name, zone());
1701a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
170243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
170343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
170443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
170543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenBlock* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
17061b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (top_scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
17074acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
170843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Block ::
170943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '{' Statement* '}'
171043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
171143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note that a Block does not introduce a new execution scope!
171243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // (ECMA-262, 3rd, 12.2)
171343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
171443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Construct block expecting 16 statements.
1715a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* result =
1716a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
1717e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, result);
171843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LBRACE, CHECK_OK);
171943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::RBRACE) {
172043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Statement* stat = ParseStatement(NULL, CHECK_OK);
17216db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    if (stat && !stat->IsEmpty()) {
1722400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      result->AddStatement(stat, zone());
17236db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    }
172443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
172543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RBRACE, CHECK_OK);
172643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
172743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
172843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
172943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17304acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.orgBlock* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
1731f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // The harmony mode uses block elements instead of statements.
1732c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  //
1733c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Block ::
1734f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //   '{' BlockElement* '}'
1735c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
17364acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // Construct block expecting 16 statements.
1737a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* body =
1738a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
1739394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
17404acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
17414acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // Parse the statements and collect escaping labels.
17424acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  Expect(Token::LBRACE, CHECK_OK);
1743394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  block_scope->set_start_position(scanner().location().beg_pos);
1744c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  { BlockState block_state(this, block_scope);
17457028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    TargetCollector collector(zone());
1746394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Target target(&this->target_stack_, &collector);
17474acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    Target target_body(&this->target_stack_, body);
17484acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
17494acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    while (peek() != Token::RBRACE) {
1750f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      Statement* stat = ParseBlockElement(NULL, CHECK_OK);
17514acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      if (stat && !stat->IsEmpty()) {
1752400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body->AddStatement(stat, zone());
17534acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      }
17544acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    }
17554acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  }
17564acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  Expect(Token::RBRACE, CHECK_OK);
1757394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  block_scope->set_end_position(scanner().location().end_pos);
17581805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  block_scope = block_scope->FinalizeBlockScope();
1759ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  body->set_scope(block_scope);
1760486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  return body;
17614acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org}
17624acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
17634acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
1764b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgBlock* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
1765812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org                                      ZoneStringList* names,
1766b645116853c677aca8a316381b87441ba6004f67danno@chromium.org                                      bool* ok) {
176743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // VariableStatement ::
176843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   VariableDeclarations ';'
176943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17704f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Handle<String> ignore;
1771f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Block* result =
1772812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
177343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
177443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
177543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
177643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1777ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
1778ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgbool Parser::IsEvalOrArguments(Handle<String> string) {
17794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  return string.is_identical_to(isolate()->factory()->eval_string()) ||
17804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      string.is_identical_to(isolate()->factory()->arguments_string());
17810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org}
178243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1783ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
178443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// If the variable declaration declares exactly one non-const
178578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org// variable, then *out is set to that variable. In all other cases,
178678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org// *out is untouched; in particular, it is the caller's responsibility
178743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// to initialize it properly. This mechanism is used for the parsing
178843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// of 'for-in' loops.
1789394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comBlock* Parser::ParseVariableDeclarations(
1790394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    VariableDeclarationContext var_context,
1791394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    VariableDeclarationProperties* decl_props,
1792812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    ZoneStringList* names,
1793394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Handle<String>* out,
1794394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    bool* ok) {
179543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // VariableDeclarations ::
1796394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
1797394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //
1798394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // The ES6 Draft Rev3 specifies the following grammar for const declarations
1799394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //
1800394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ConstDeclaration ::
1801394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   const ConstBinding (',' ConstBinding)* ';'
1802394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ConstBinding ::
1803394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   Identifier '=' AssignmentExpression
1804394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //
1805394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // TODO(ES6):
1806394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ConstBinding ::
1807394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   BindingPattern '=' AssignmentExpression
1808a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org
1809a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1810b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  VariableMode mode = VAR;
181180c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // True if the binding needs initialization. 'let' and 'const' declared
181280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // bindings are created uninitialized by their declaration nodes and
181380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // need initialization. 'var' declared bindings are always initialized
181480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // immediately by their declaration nodes.
181580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  bool needs_init = false;
181643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool is_const = false;
181780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  Token::Value init_op = Token::INIT_VAR;
181843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::VAR) {
181943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::VAR);
182043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else if (peek() == Token::CONST) {
18211b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
18221b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
18231b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
18241b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
18251b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // * It is a Syntax Error if the code that matches this production is not
18261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   contained in extended code.
18271b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
18281b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // However disallowing const in classic mode will break compatibility with
18291b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // existing pages. Therefore we keep allowing const with the old
18301b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // non-harmony semantics in classic mode.
183143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::CONST);
18321b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    switch (top_scope_->language_mode()) {
18331b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      case CLASSIC_MODE:
18341b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        mode = CONST;
18351b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        init_op = Token::INIT_CONST;
18361b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        break;
18371b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      case STRICT_MODE:
18381b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        ReportMessage("strict_const", Vector<const char*>::empty());
1839394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        *ok = false;
1840394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        return NULL;
18411b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      case EXTENDED_MODE:
1842f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org        if (var_context == kStatement) {
18431b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          // In extended mode 'const' declarations are only allowed in source
18441b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          // element positions.
18451b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          ReportMessage("unprotected_const", Vector<const char*>::empty());
18461b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          *ok = false;
18471b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          return NULL;
18481b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        }
18491b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        mode = CONST_HARMONY;
18501b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        init_op = Token::INIT_CONST_HARMONY;
18519ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    }
185243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    is_const = true;
185380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    needs_init = true;
1854b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  } else if (peek() == Token::LET) {
18551b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // ES6 Draft Rev4 section 12.2.1:
18561b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
18571b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // LetDeclaration : let LetBindingList ;
18581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
18591b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // * It is a Syntax Error if the code that matches this production is not
18601b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   contained in extended code.
18611b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (!is_extended_mode()) {
18621b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      ReportMessage("illegal_let", Vector<const char*>::empty());
18631b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      *ok = false;
18641b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      return NULL;
18651b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    }
1866b645116853c677aca8a316381b87441ba6004f67danno@chromium.org    Consume(Token::LET);
1867f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    if (var_context == kStatement) {
1868394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // Let declarations are only allowed in source element positions.
1869b645116853c677aca8a316381b87441ba6004f67danno@chromium.org      ReportMessage("unprotected_let", Vector<const char*>::empty());
1870b645116853c677aca8a316381b87441ba6004f67danno@chromium.org      *ok = false;
1871b645116853c677aca8a316381b87441ba6004f67danno@chromium.org      return NULL;
1872b645116853c677aca8a316381b87441ba6004f67danno@chromium.org    }
1873b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    mode = LET;
187480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    needs_init = true;
187580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    init_op = Token::INIT_LET;
187643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
187743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    UNREACHABLE();  // by current callers
187843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
187943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1880812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Scope* declaration_scope = DeclarationScope(mode);
1881812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1882b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // The scope of a var/const declared variable anywhere inside a function
188343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1884b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // transform a source-level var/const declaration into a (Function)
188543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Scope declaration, and rewrite the source-level initialization into an
188643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // assignment statement. We use a block to collect multiple assignments.
188743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
188843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // We mark the block as initializer block because we don't want the
188943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // rewriter to add a '.result' assignment to such a block (to get compliant
189043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // behavior for code such as print(eval('var x = 7')), and for cosmetic
189143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // reasons when pretty-printing. Also, unless an assignment (initialization)
189243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // is inside an initializer block, it is ignored.
189343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
189443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Create new block with one expected declaration.
1895a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* block = factory()->NewBlock(NULL, 1, true, pos);
189643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int nvars = 0;  // the number of variables declared
18974f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Handle<String> name;
189843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  do {
189965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->Enter();
190065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
190143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Parse variable name.
190243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (nvars > 0) Consume(Token::COMMA);
19034f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    name = ParseIdentifier(CHECK_OK);
190465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->PushVariableName(name);
190543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19060a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Strict mode variables may not be named eval or arguments
19071b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (!declaration_scope->is_classic_mode() && IsEvalOrArguments(name)) {
19080a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      ReportMessage("strict_var_name", Vector<const char*>::empty());
19090a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      *ok = false;
19100a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      return NULL;
19110a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
19120a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
191343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Declare variable.
191443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Note that we *always* must treat the initial value via a separate init
191543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // assignment for variables and constants because the value must be assigned
191643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // when the variable is encountered in the source. But the variable/constant
191743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is declared (and set to 'undefined') upon entering the function within
191843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // which the variable or constant is declared. Only function variables have
191943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // an initial value in the declaration (because they are initialized upon
192043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // entering the function).
192143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
192243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If we have a const declaration, in an inner scope, the proxy is always
192343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // bound to the declared variable (independent of possibly surrounding with
192443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // statements).
1925394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // For let/const declarations in harmony mode, we can also immediately
1926394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // pre-resolve the proxy because it resides in the same scope as the
1927394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // declaration.
192828583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    Interface* interface =
192928583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org        is_const ? Interface::NewConst() : Interface::NewValue();
193028583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    VariableProxy* proxy = NewUnresolved(name, mode, interface);
1931812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declaration* declaration =
1932a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        factory()->NewVariableDeclaration(proxy, mode, top_scope_, pos);
1933812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declare(declaration, mode != VAR, CHECK_OK);
193443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    nvars++;
19354f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
19367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      ReportMessageAt(scanner().location(), "too_many_variables",
19377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                      Vector<const char*>::empty());
19387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      *ok = false;
19397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return NULL;
19407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
19417028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (names) names->Add(name, zone());
194243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
194343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Parse initialization expression if present and/or needed. A
194443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration of the form:
194543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
194643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //    var v = x;
194743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
194843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is syntactic sugar for:
194943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
195043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //    var v; v = x;
195143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
19524f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // In particular, we need to re-lookup 'v' (in top_scope_, not
19534f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // declaration_scope) as it may be a different 'v' than the 'v' in the
19544f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // declaration (e.g., if we are inside a 'with' statement or 'catch'
19554f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // block).
195643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
195743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // However, note that const declarations are different! A const
195843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration of the form:
195943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
196043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //   const c = x;
196143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
196243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is *not* syntactic sugar for:
196343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
196443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //   const c; c = x;
196543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
196643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // The "variable" c initialized to x is the same as the declared
196743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // one - there is no re-lookup (see the last parameter of the
196843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Declare() call above).
196943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19704f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
197143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* value = NULL;
1972a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int pos = -1;
1973394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Harmony consts have non-optional initializers.
1974394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    if (peek() == Token::ASSIGN || mode == CONST_HARMONY) {
197543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expect(Token::ASSIGN, CHECK_OK);
1976a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      pos = position();
1977b645116853c677aca8a316381b87441ba6004f67danno@chromium.org      value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
197865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      // Don't infer if it is "a = function(){...}();"-like expression.
197904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      if (fni_ != NULL &&
198004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org          value->AsCall() == NULL &&
198104921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org          value->AsCallNew() == NULL) {
198204921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org        fni_->Infer();
1983c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      } else {
1984c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        fni_->RemoveLastFunction();
198504921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      }
1986394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      if (decl_props != NULL) *decl_props = kHasInitializers;
198743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
198843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1989c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    // Record the end position of the initializer.
1990c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    if (proxy->var() != NULL) {
1991a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      proxy->var()->set_initializer_position(position());
1992c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    }
1993c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
199480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
199580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    if (value == NULL && needs_init) {
1996a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      value = GetLiteralUndefined(position());
199743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
199843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
199943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Global variable declarations must be compiled in a specific
200043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // way. When the script containing the global variable declaration
200143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is entered, the global variable must be declared, so that if it
2002ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    // doesn't exist (on the global object itself, see ES5 errata) it
200343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // gets created with an initial undefined value. This is handled
200443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // by the declarations part of the function representing the
200543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // top-level global code; see Runtime::DeclareGlobalVariable. If
200643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // it already exists (in the object or in a prototype), it is
200743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // *not* touched until the variable declaration statement is
200843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // executed.
200943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
201043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Executing the variable declaration statement will always
201143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // guarantee to give the global object a "local" variable; a
201243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // variable defined in the global object and not in any
201343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // prototype. This way, global variable declarations can shadow
201443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // properties in the prototype chain, but only after the variable
201543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration statement has been executed. This is important in
201643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // browsers where the global object (window) has lots of
201743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // properties defined in prototype objects.
2018355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    if (initialization_scope->is_global_scope() &&
2019355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        !IsLexicalVariableMode(mode)) {
202043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // Compute the arguments for the runtime call.
20217028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ZoneList<Expression*>* arguments =
20227028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          new(zone()) ZoneList<Expression*>(3, zone());
2023c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      // We have at least 1 parameter.
2024a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      arguments->Add(factory()->NewLiteral(name, pos), zone());
202543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      CallRuntime* initialize;
20269ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
202743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (is_const) {
20287028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        arguments->Add(value, zone());
20299ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        value = NULL;  // zap the value to avoid the unnecessary assignment
20309ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20319ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Construct the call to Runtime_InitializeConstGlobal
20329ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // and add it to the initialization statement block.
20339ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Note that the function does different things depending on
20349ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // the number of arguments (1 or 2).
2035b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        initialize = factory()->NewCallRuntime(
20364a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org            isolate()->factory()->InitializeConstGlobal_string(),
2037b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
2038a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            arguments, pos);
203943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
20409ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Add strict mode.
20419ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // We may want to pass singleton to avoid Literal allocations.
20421b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        LanguageMode language_mode = initialization_scope->language_mode();
2043a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        arguments->Add(factory()->NewNumberLiteral(language_mode, pos), zone());
20449ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20459ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Be careful not to assign a value to the global variable if
20469ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // we're in a with. The initialization value should not
20479ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // necessarily be stored in the global object in that case,
20489ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // which is why we need to generate a separate assignment node.
20499ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        if (value != NULL && !inside_with()) {
20507028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          arguments->Add(value, zone());
20519ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          value = NULL;  // zap the value to avoid the unnecessary assignment
20529ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        }
20539ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20549ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Construct the call to Runtime_InitializeVarGlobal
20559ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // and add it to the initialization statement block.
20569ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Note that the function does different things depending on
20579ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // the number of arguments (2 or 3).
2058b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        initialize = factory()->NewCallRuntime(
20594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org            isolate()->factory()->InitializeVarGlobal_string(),
2060b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
2061a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            arguments, pos);
206243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
20639ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
2064a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      block->AddStatement(
2065a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
2066a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          zone());
206727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    } else if (needs_init) {
206827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // Constant initializations always assign to the declared constant which
206927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // is always at the function scope level. This is only relevant for
207027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // dynamically looked-up variables and constants (the start context for
207127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // constant lookups is always the function context, while it is the top
207227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // context for var declared variables). Sigh...
207327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // For 'let' and 'const' declared variables in harmony mode the
207427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // initialization also always assigns to the declared variable.
207527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      ASSERT(proxy != NULL);
207627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      ASSERT(proxy->var() != NULL);
207727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      ASSERT(value != NULL);
207827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      Assignment* assignment =
2079a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewAssignment(init_op, proxy, value, pos);
2080a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      block->AddStatement(
2081a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2082a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          zone());
208327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      value = NULL;
208443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
208543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2086486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Add an assignment node to the initialization statement block if we still
208727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // have a pending initialization value.
208843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (value != NULL) {
208927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      ASSERT(mode == VAR);
209027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // 'var' initializations are simply assignments (with all the consequences
209127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // if they are inside a 'with' statement - they may change a 'with' object
209227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // property).
2093b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      VariableProxy* proxy =
209428583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org          initialization_scope->NewUnresolved(factory(), name, interface);
2095c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      Assignment* assignment =
2096a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewAssignment(init_op, proxy, value, pos);
2097a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      block->AddStatement(
2098a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2099a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          zone());
210043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
210165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
210265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->Leave();
210343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } while (peek() == Token::COMMA);
210443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
21054f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // If there was a single non-const declaration, return it in the output
21064f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // parameter for possible use by for/in.
21074f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (nvars == 1 && !is_const) {
21084f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    *out = name;
210943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
211043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
211143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return block;
211243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
211343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
211443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
211543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
211643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(!label.is_null());
211743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (labels != NULL)
211843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    for (int i = labels->length(); i-- > 0; )
211943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (labels->at(i).is_identical_to(label))
212043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return true;
212143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
212243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return false;
212343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
212443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
212543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
212643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
212743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                                      bool* ok) {
212843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ExpressionStatement | LabelledStatement ::
212943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Expression ';'
213043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Identifier ':' Statement
2131a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
213283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  bool starts_with_idenfifier = peek_any_identifier();
213343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* expr = ParseExpression(true, CHECK_OK);
21347b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
213543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      expr->AsVariableProxy() != NULL &&
213643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      !expr->AsVariableProxy()->is_this()) {
21374a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    // Expression is a single identifier, and not, e.g., a parenthesized
21384a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    // identifier.
213943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    VariableProxy* var = expr->AsVariableProxy();
214043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Handle<String> label = var->name();
214143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // TODO(1240780): We don't check for redeclaration of labels
214243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // during preparsing since keeping track of the set of active
214343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // labels requires nontrivial changes to the way scopes are
214443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // structured.  However, these are probably changes we want to
214543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // make later anyway so we should go back and fix this then.
2146fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
214783e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org      SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
2148fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      const char* elms[2] = { "Label", *c_string };
2149fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      Vector<const char*> args(elms, 2);
2150fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      ReportMessage("redeclaration", args);
2151fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      *ok = false;
2152fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      return NULL;
215343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
21547028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (labels == NULL) {
21557028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      labels = new(zone()) ZoneStringList(4, zone());
21567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    }
21577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    labels->Add(label, zone());
2158fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    // Remove the "ghost" variable that turned out to be a label
2159fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    // from the top scope. This way, we don't try to resolve it
2160fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    // during the scope processing.
2161fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    top_scope_->RemoveUnresolved(var);
216243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::COLON, CHECK_OK);
216343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return ParseStatement(labels, ok);
216443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
216543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
21667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // If we have an extension, we allow a native function declaration.
21677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // A native function declaration starts with "native function" with
21687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // no line-terminator between the two words.
21697b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  if (extension_ != NULL &&
21707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      peek() == Token::FUNCTION &&
2171df8c03c138809b385f3cca5d424d7b2f8ad92527whesse@chromium.org      !scanner().HasAnyLineTerminatorBeforeNext() &&
21727b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      expr != NULL &&
21737b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      expr->AsVariableProxy() != NULL &&
21747b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      expr->AsVariableProxy()->name()->Equals(
21754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org          isolate()->heap()->native_string()) &&
21767b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      !scanner().literal_contains_escapes()) {
21777b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    return ParseNativeDeclaration(ok);
21787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  }
21797b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
2180a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  // Parsed expression statement, or the context-sensitive 'module' keyword.
2181a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  // Only expect semicolon in the former case.
2182a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  if (!FLAG_harmony_modules ||
2183a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      peek() != Token::IDENTIFIER ||
2184a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      scanner().HasAnyLineTerminatorBeforeNext() ||
2185a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      expr->AsVariableProxy() == NULL ||
2186a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      !expr->AsVariableProxy()->name()->Equals(
21874a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org          isolate()->heap()->module_string()) ||
2188a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      scanner().literal_contains_escapes()) {
2189a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org    ExpectSemicolon(CHECK_OK);
2190a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  }
2191a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewExpressionStatement(expr, pos);
219243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
219343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
219443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
219543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenIfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
219643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // IfStatement ::
219743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'if' '(' Expression ')' Statement ('else' Statement)?
219843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2199a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
220043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::IF, CHECK_OK);
220143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
220243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* condition = ParseExpression(true, CHECK_OK);
220343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
220443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* then_statement = ParseStatement(labels, CHECK_OK);
220543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* else_statement = NULL;
220643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::ELSE) {
220743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Next();
220843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    else_statement = ParseStatement(labels, CHECK_OK);
2209fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  } else {
2210a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
221143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
2212a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewIfStatement(
2213a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      condition, then_statement, else_statement, pos);
221443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
221543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
221643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
221743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseContinueStatement(bool* ok) {
221843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ContinueStatement ::
221943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'continue' Identifier? ';'
222043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2221a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
222243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::CONTINUE, CHECK_OK);
222368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  Handle<String> label = Handle<String>::null();
222443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value tok = peek();
2225df8c03c138809b385f3cca5d424d7b2f8ad92527whesse@chromium.org  if (!scanner().HasAnyLineTerminatorBeforeNext() &&
22269258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
222743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    label = ParseIdentifier(CHECK_OK);
222843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
222943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  IterationStatement* target = NULL;
2230fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  target = LookupContinueTarget(label, CHECK_OK);
2231fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (target == NULL) {
2232c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    // Illegal continue statement.
2233c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    const char* message = "illegal_continue";
2234c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    Vector<Handle<String> > args;
2235c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    if (!label.is_null()) {
2236c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      message = "unknown_label";
2237c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      args = Vector<Handle<String> >(&label, 1);
2238c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    }
2239c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    ReportMessageAt(scanner().location(), message, args);
2240c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    *ok = false;
2241c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return NULL;
224243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
224343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
2244a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewContinueStatement(target, pos);
224543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
224643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
224743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
224843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
224943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // BreakStatement ::
225043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'break' Identifier? ';'
225143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2252a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
225343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::BREAK, CHECK_OK);
225443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Handle<String> label;
225543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value tok = peek();
2256df8c03c138809b385f3cca5d424d7b2f8ad92527whesse@chromium.org  if (!scanner().HasAnyLineTerminatorBeforeNext() &&
22579258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
225843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    label = ParseIdentifier(CHECK_OK);
225943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
22603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Parse labeled break statements that target themselves into
226143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // empty statements, e.g. 'l1: l2: l3: break l2;'
226243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (!label.is_null() && ContainsLabel(labels, label)) {
2263b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    ExpectSemicolon(CHECK_OK);
2264a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewEmptyStatement(pos);
226543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
226643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  BreakableStatement* target = NULL;
2267fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  target = LookupBreakTarget(label, CHECK_OK);
2268fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (target == NULL) {
2269c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    // Illegal break statement.
2270c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    const char* message = "illegal_break";
2271c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    Vector<Handle<String> > args;
2272c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    if (!label.is_null()) {
2273c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      message = "unknown_label";
2274c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      args = Vector<Handle<String> >(&label, 1);
2275c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    }
2276c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    ReportMessageAt(scanner().location(), message, args);
2277c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    *ok = false;
2278c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return NULL;
227943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
228043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
2281a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewBreakStatement(target, pos);
228243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
228343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
228443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
228543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseReturnStatement(bool* ok) {
228643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ReturnStatement ::
228743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'return' Expression? ';'
228843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2289a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  // Consume the return token. It is necessary to do that before
229043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // reporting any errors on it, because of the way errors are
229143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // reported (underlining).
229243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RETURN, CHECK_OK);
2293a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
229443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
229564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Token::Value tok = peek();
229664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Statement* result;
229777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  Expression* return_value;
229864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (scanner().HasAnyLineTerminatorBeforeNext() ||
229964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      tok == Token::SEMICOLON ||
230064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      tok == Token::RBRACE ||
230164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      tok == Token::EOS) {
2302a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return_value = GetLiteralUndefined(position());
230364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else {
230477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    return_value = ParseExpression(true, CHECK_OK);
230577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  }
230677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  ExpectSemicolon(CHECK_OK);
230777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  if (is_generator()) {
230877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    Expression* generator = factory()->NewVariableProxy(
230977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org        current_function_state_->generator_object_variable());
231077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    Expression* yield = factory()->NewYield(
2311a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        generator, return_value, Yield::FINAL, pos);
2312a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    result = factory()->NewExpressionStatement(yield, pos);
231377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  } else {
2314a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    result = factory()->NewReturnStatement(return_value, pos);
231564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
231664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
231743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // An ECMAScript program is considered syntactically incorrect if it
231843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // contains a return statement that is not within the body of a
231943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // function. See ECMA-262, section 12.9, page 67.
232043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
232143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // To be consistent with KJS we report the syntax error at runtime.
23224f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Scope* declaration_scope = top_scope_->DeclarationScope();
23234f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (declaration_scope->is_global_scope() ||
23244f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      declaration_scope->is_eval_scope()) {
2325dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    Handle<String> message = isolate()->factory()->illegal_return_string();
2326dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    Expression* throw_error =
2327dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org        NewThrowSyntaxError(message, Handle<Object>::null());
2328a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewExpressionStatement(throw_error, pos);
232943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
233064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  return result;
233143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
233243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
233343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
233443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
233543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // WithStatement ::
233643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'with' '(' Expression ')' Statement
233743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
233843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::WITH, CHECK_OK);
2339a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
23400a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
23411b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (!top_scope_->is_classic_mode()) {
23420a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    ReportMessage("strict_mode_with", Vector<const char*>::empty());
23430a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    *ok = false;
23440a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    return NULL;
23450a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  }
23460a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
234743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
234843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* expr = ParseExpression(true, CHECK_OK);
234943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
235043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23514acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  top_scope_->DeclarationScope()->RecordWithStatement();
2352394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Scope* with_scope = NewScope(top_scope_, WITH_SCOPE);
2353394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Statement* stmt;
2354c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  { BlockState block_state(this, with_scope);
2355394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    with_scope->set_start_position(scanner().peek_location().beg_pos);
2356394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    stmt = ParseStatement(labels, CHECK_OK);
2357394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    with_scope->set_end_position(scanner().location().end_pos);
2358394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
2359a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewWithStatement(with_scope, expr, stmt, pos);
236043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
236143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
236243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
236343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenCaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
236443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // CaseClause ::
236543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'case' Expression ':' Statement*
236643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'default' ':' Statement*
236743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
236843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* label = NULL;  // NULL expression indicates default case
236943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::CASE) {
237043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::CASE, CHECK_OK);
237143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    label = ParseExpression(true, CHECK_OK);
237243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
237343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::DEFAULT, CHECK_OK);
237443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (*default_seen_ptr) {
237543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      ReportMessage("multiple_defaults_in_switch",
237643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                    Vector<const char*>::empty());
237743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      *ok = false;
237843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return NULL;
237943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
238043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *default_seen_ptr = true;
238143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
238243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::COLON, CHECK_OK);
2383a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
23847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<Statement*>* statements =
23857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      new(zone()) ZoneList<Statement*>(5, zone());
238643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::CASE &&
238743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen         peek() != Token::DEFAULT &&
238843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen         peek() != Token::RBRACE) {
238943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Statement* stat = ParseStatement(NULL, CHECK_OK);
23907028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    statements->Add(stat, zone());
239143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
239243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2393a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewCaseClause(label, statements, pos);
239443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
239543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
239643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
239743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenSwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
239843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                              bool* ok) {
239943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // SwitchStatement ::
240043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'switch' '(' Expression ')' '{' CaseClause* '}'
240143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2402a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  SwitchStatement* statement =
2403a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewSwitchStatement(labels, peek_position());
2404e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, statement);
240543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
240643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SWITCH, CHECK_OK);
240743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
240843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* tag = ParseExpression(true, CHECK_OK);
240943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
241043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
241143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool default_seen = false;
24127028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4, zone());
241343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LBRACE, CHECK_OK);
241443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::RBRACE) {
241543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
24167028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    cases->Add(clause, zone());
241743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
241843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RBRACE, CHECK_OK);
241943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2420fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (statement) statement->Initialize(tag, cases);
242143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return statement;
242243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
242343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
242443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
242543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseThrowStatement(bool* ok) {
242643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ThrowStatement ::
242743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'throw' Expression ';'
242843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
242943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::THROW, CHECK_OK);
2430a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
2431df8c03c138809b385f3cca5d424d7b2f8ad92527whesse@chromium.org  if (scanner().HasAnyLineTerminatorBeforeNext()) {
243243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ReportMessage("newline_after_throw", Vector<const char*>::empty());
243343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *ok = false;
243443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return NULL;
243543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
243643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* exception = ParseExpression(true, CHECK_OK);
243743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
243843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2439a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewExpressionStatement(
2440a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewThrow(exception, pos), pos);
244143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
244243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
244343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
244443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenTryStatement* Parser::ParseTryStatement(bool* ok) {
244543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // TryStatement ::
244643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'try' Block Catch
244743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'try' Block Finally
244843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'try' Block Catch Finally
244943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
245043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Catch ::
245143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'catch' '(' Identifier ')' Block
245243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
245343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Finally ::
245443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'finally' Block
245543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
245643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::TRY, CHECK_OK);
2457a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
245843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24597028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  TargetCollector try_collector(zone());
246043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Block* try_block;
246143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24626d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  { Target target(&this->target_stack_, &try_collector);
246343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    try_block = ParseBlock(NULL, CHECK_OK);
246443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
246543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
246643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value tok = peek();
246743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (tok != Token::CATCH && tok != Token::FINALLY) {
246843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
246943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *ok = false;
247043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return NULL;
247143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
247243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
247343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // If we can break out from the catch block and there is a finally block,
24746d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // then we will need to collect escaping targets from the catch
24756d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // block. Since we don't know yet if there will be a finally block, we
24766d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // always collect the targets.
24777028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  TargetCollector catch_collector(zone());
24784f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Scope* catch_scope = NULL;
24794f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Variable* catch_variable = NULL;
24806d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  Block* catch_block = NULL;
24816d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  Handle<String> name;
248243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (tok == Token::CATCH) {
248343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::CATCH);
248443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
248543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::LPAREN, CHECK_OK);
2486394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    catch_scope = NewScope(top_scope_, CATCH_SCOPE);
2487394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    catch_scope->set_start_position(scanner().location().beg_pos);
24886d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    name = ParseIdentifier(CHECK_OK);
24890a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
24901b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (!top_scope_->is_classic_mode() && IsEvalOrArguments(name)) {
24910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      ReportMessage("strict_catch_variable", Vector<const char*>::empty());
24920a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      *ok = false;
24930a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      return NULL;
24940a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
24950a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
249643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::RPAREN, CHECK_OK);
249743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
249843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (peek() == Token::LBRACE) {
24994acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      Target target(&this->target_stack_, &catch_collector);
25001b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      VariableMode mode = is_extended_mode() ? LET : VAR;
2501c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      catch_variable =
2502c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
25034acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
2504c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      BlockState block_state(this, catch_scope);
250555ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org      catch_block = ParseBlock(NULL, CHECK_OK);
250643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
250743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expect(Token::LBRACE, CHECK_OK);
250843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
2509394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    catch_scope->set_end_position(scanner().location().end_pos);
251043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    tok = peek();
251143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
251243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25136d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  Block* finally_block = NULL;
25146d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  if (tok == Token::FINALLY || catch_block == NULL) {
251543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::FINALLY);
251643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    finally_block = ParseBlock(NULL, CHECK_OK);
251743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
251843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
251943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Simplify the AST nodes by converting:
25206d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  //   'try B0 catch B1 finally B2'
252143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // to:
25226d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  //   'try { try B0 catch B1 } finally B2'
252343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2524fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (catch_block != NULL && finally_block != NULL) {
25254f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // If we have both, create an inner try/catch.
25264f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    ASSERT(catch_scope != NULL && catch_variable != NULL);
252704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    int index = current_function_state_->NextHandlerIndex();
2528b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    TryCatchStatement* statement = factory()->NewTryCatchStatement(
2529a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        index, try_block, catch_scope, catch_variable, catch_block,
2530a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        RelocInfo::kNoPosition);
25316d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    statement->set_escaping_targets(try_collector.targets());
2532a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2533400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org    try_block->AddStatement(statement, zone());
25344f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    catch_block = NULL;  // Clear to indicate it's been handled.
253543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
253643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
253743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  TryStatement* result = NULL;
2538fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (catch_block != NULL) {
2539fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    ASSERT(finally_block == NULL);
25404f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    ASSERT(catch_scope != NULL && catch_variable != NULL);
254104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    int index = current_function_state_->NextHandlerIndex();
2542b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    result = factory()->NewTryCatchStatement(
2543a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        index, try_block, catch_scope, catch_variable, catch_block, pos);
2544fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  } else {
2545fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    ASSERT(finally_block != NULL);
254604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    int index = current_function_state_->NextHandlerIndex();
2547a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    result = factory()->NewTryFinallyStatement(
2548a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        index, try_block, finally_block, pos);
25496d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    // Combine the jump targets of the try block and the possible catch block.
25507028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    try_collector.targets()->AddAll(*catch_collector.targets(), zone());
255143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
255243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25536d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  result->set_escaping_targets(try_collector.targets());
255443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
255543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
255643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
255743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comDoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
25599d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                                                bool* ok) {
256043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // DoStatement ::
256143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'do' Statement 'while' '(' Expression ')' ';'
256243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2563a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  DoWhileStatement* loop =
2564a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewDoWhileStatement(labels, peek_position());
2565e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, loop);
256643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
256743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::DO, CHECK_OK);
256843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* body = ParseStatement(NULL, CHECK_OK);
256943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::WHILE, CHECK_OK);
257043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
2571c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
257243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* cond = ParseExpression(true, CHECK_OK);
257343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
257443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
257543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Allow do-statements to be terminated with and without
257643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // semi-colons. This allows code such as 'do;while(0)return' to
257743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // parse, which would not be the case if we had used the
257843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ExpectSemicolon() functionality here.
257943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
258043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25819d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (loop != NULL) loop->Initialize(cond, body);
258243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return loop;
258343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
258443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
258543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25869d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comWhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
258743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // WhileStatement ::
258843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'while' '(' Expression ')' Statement
258943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2590a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
2591e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, loop);
259243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
259343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::WHILE, CHECK_OK);
259443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
259543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* cond = ParseExpression(true, CHECK_OK);
259643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
259743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* body = ParseStatement(NULL, CHECK_OK);
259843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25999d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (loop != NULL) loop->Initialize(cond, body);
260043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return loop;
260143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
260243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
260343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
260441728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.orgbool Parser::CheckInOrOf(bool accept_OF,
260541728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org                         ForEachStatement::VisitMode* visit_mode) {
26061fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  if (Check(Token::IN)) {
26071fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    *visit_mode = ForEachStatement::ENUMERATE;
26081fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    return true;
260941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  } else if (allow_for_of() && accept_OF &&
261041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org             CheckContextualKeyword(CStrVector("of"))) {
26111fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    *visit_mode = ForEachStatement::ITERATE;
26121fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    return true;
26131fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  }
26141fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  return false;
26151fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org}
26161fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26171fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26181fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.orgvoid Parser::InitializeForEachStatement(ForEachStatement* stmt,
26191fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                                        Expression* each,
26201fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                                        Expression* subject,
26211fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                                        Statement* body) {
26221fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  ForOfStatement* for_of = stmt->AsForOfStatement();
26231fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26241fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  if (for_of != NULL) {
26251fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Factory* heap_factory = isolate()->factory();
2626e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Variable* iterator = top_scope_->DeclarationScope()->NewTemporary(
2627e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        heap_factory->dot_iterator_string());
2628e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Variable* result = top_scope_->DeclarationScope()->NewTemporary(
2629e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        heap_factory->dot_result_string());
26301fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26311fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* assign_iterator;
26321fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* next_result;
26331fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* result_done;
26341fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* assign_each;
26351fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26361fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    // var iterator = iterable;
26371fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    {
26381fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
26391fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      assign_iterator = factory()->NewAssignment(
26401fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          Token::ASSIGN, iterator_proxy, subject, RelocInfo::kNoPosition);
26411fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    }
26421fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26431fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    // var result = iterator.next();
26441fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    {
26451fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
2646a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      Expression* next_literal = factory()->NewLiteral(
2647a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          heap_factory->next_string(), RelocInfo::kNoPosition);
26481fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* next_property = factory()->NewProperty(
26491fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          iterator_proxy, next_literal, RelocInfo::kNoPosition);
26501fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ZoneList<Expression*>* next_arguments =
26511fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          new(zone()) ZoneList<Expression*>(0, zone());
26521fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* next_call = factory()->NewCall(
26531fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          next_property, next_arguments, RelocInfo::kNoPosition);
26541fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_proxy = factory()->NewVariableProxy(result);
26551fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      next_result = factory()->NewAssignment(
26561fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition);
26571fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    }
26581fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26591fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    // result.done
26601fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    {
2661a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      Expression* done_literal = factory()->NewLiteral(
2662a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          heap_factory->done_string(), RelocInfo::kNoPosition);
26631fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_proxy = factory()->NewVariableProxy(result);
26641fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      result_done = factory()->NewProperty(
26651fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          result_proxy, done_literal, RelocInfo::kNoPosition);
26661fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    }
26671fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26681fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    // each = result.value
26691fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    {
2670a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      Expression* value_literal = factory()->NewLiteral(
2671a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          heap_factory->value_string(), RelocInfo::kNoPosition);
26721fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_proxy = factory()->NewVariableProxy(result);
26731fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_value = factory()->NewProperty(
26741fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          result_proxy, value_literal, RelocInfo::kNoPosition);
26751fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      assign_each = factory()->NewAssignment(
26761fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          Token::ASSIGN, each, result_value, RelocInfo::kNoPosition);
26771fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    }
26781fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26791fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    for_of->Initialize(each, subject, body,
26801fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                       assign_iterator, next_result, result_done, assign_each);
26811fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  } else {
26821fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    stmt->Initialize(each, subject, body);
26831fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  }
26841fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org}
26851fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
26861fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
268743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
268843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ForStatement ::
268943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
269043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2691a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
269243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* init = NULL;
269343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2694394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Create an in-between scope for let-bound iteration variables.
2695394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Scope* saved_scope = top_scope_;
2696394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
2697394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  top_scope_ = for_scope;
2698394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
269943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::FOR, CHECK_OK);
270043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
2701394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  for_scope->set_start_position(scanner().location().beg_pos);
270243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() != Token::SEMICOLON) {
270343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (peek() == Token::VAR || peek() == Token::CONST) {
270428583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org      bool is_const = peek() == Token::CONST;
27054f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      Handle<String> name;
270641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      VariableDeclarationProperties decl_props = kHasNoInitializers;
270743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Block* variable_statement =
270841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org          ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
270941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org                                    CHECK_OK);
271041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      bool accept_OF = decl_props == kHasNoInitializers;
27111fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ForEachStatement::VisitMode mode;
27124f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
271341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
271428583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org        Interface* interface =
271528583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org            is_const ? Interface::NewConst() : Interface::NewValue();
2716a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        ForEachStatement* loop =
2717a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewForEachStatement(mode, labels, pos);
2718e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org        Target target(&this->target_stack_, loop);
271943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
272043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expression* enumerable = ParseExpression(true, CHECK_OK);
272143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expect(Token::RPAREN, CHECK_OK);
272243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
272333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        VariableProxy* each =
272433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            top_scope_->NewUnresolved(factory(), name, interface);
272543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Statement* body = ParseStatement(NULL, CHECK_OK);
27261fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org        InitializeForEachStatement(loop, each, enumerable, body);
2727a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        Block* result =
2728a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
2729400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        result->AddStatement(variable_statement, zone());
2730400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        result->AddStatement(loop, zone());
2731394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        top_scope_ = saved_scope;
2732394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope->set_end_position(scanner().location().end_pos);
2733394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope = for_scope->FinalizeBlockScope();
2734394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        ASSERT(for_scope == NULL);
2735fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org        // Parsed for-in loop w/ variable/const declaration.
2736fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org        return result;
273743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
273843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        init = variable_statement;
273943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
2740394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    } else if (peek() == Token::LET) {
2741394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      Handle<String> name;
2742394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      VariableDeclarationProperties decl_props = kHasNoInitializers;
2743394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      Block* variable_statement =
2744812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org         ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
2745812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org                                   CHECK_OK);
2746394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
274741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      bool accept_OF = decl_props == kHasNoInitializers;
27481fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ForEachStatement::VisitMode mode;
27491fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
275041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
2751394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // Rewrite a for-in statement of the form
2752394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //
2753394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   for (let x in e) b
2754394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //
2755394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // into
2756394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //
2757394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   <let x' be a temporary variable>
2758394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   for (x' in e) {
2759394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //     let x;
2760394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //     x = x';
2761394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //     b;
2762394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   }
2763394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
2764394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // TODO(keuchel): Move the temporary variable to the block scope, after
2765394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // implementing stack allocated block scoped variables.
276633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        Factory* heap_factory = isolate()->factory();
276733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        Handle<String> tempstr =
27684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org            heap_factory->NewConsString(heap_factory->dot_for_string(), name);
27694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        Handle<String> tempname = heap_factory->InternalizeString(tempstr);
277033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        Variable* temp = top_scope_->DeclarationScope()->NewTemporary(tempname);
2771b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
2772a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        ForEachStatement* loop =
2773a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewForEachStatement(mode, labels, pos);
2774394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Target target(&this->target_stack_, loop);
2775394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
277633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        // The expression does not see the loop variable.
277733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        top_scope_ = saved_scope;
2778394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Expression* enumerable = ParseExpression(true, CHECK_OK);
277933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        top_scope_ = for_scope;
2780394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Expect(Token::RPAREN, CHECK_OK);
278143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
278233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        VariableProxy* each =
278333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            top_scope_->NewUnresolved(factory(), name, Interface::NewValue());
2784394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Statement* body = ParseStatement(NULL, CHECK_OK);
2785a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        Block* body_block =
2786a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
2787b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        Assignment* assignment = factory()->NewAssignment(
2788b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
2789a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        Statement* assignment_statement = factory()->NewExpressionStatement(
2790a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            assignment, RelocInfo::kNoPosition);
2791400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body_block->AddStatement(variable_statement, zone());
2792400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body_block->AddStatement(assignment_statement, zone());
2793400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body_block->AddStatement(body, zone());
27941fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org        InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
2795394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        top_scope_ = saved_scope;
2796394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope->set_end_position(scanner().location().end_pos);
2797394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope = for_scope->FinalizeBlockScope();
2798ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        body_block->set_scope(for_scope);
2799394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // Parsed for-in loop w/ let declaration.
2800394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        return loop;
2801394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
2802394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      } else {
2803394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        init = variable_statement;
2804394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
280543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
280643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expression* expression = ParseExpression(false, CHECK_OK);
28071fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ForEachStatement::VisitMode mode;
280841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      bool accept_OF = expression->AsVariableProxy();
28091fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
281041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      if (CheckInOrOf(accept_OF, &mode)) {
2811c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org        // Signal a reference error if the expression is an invalid
2812c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org        // left-hand side expression.  We could report this as a syntax
2813c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org        // error here but for compatibility with JSC we choose to report
2814c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org        // the error at runtime.
281543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (expression == NULL || !expression->IsValidLeftHandSide()) {
2816dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org          Handle<String> message =
28174a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org              isolate()->factory()->invalid_lhs_in_for_in_string();
2818dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org          expression = NewThrowReferenceError(message);
281943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
2820a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        ForEachStatement* loop =
2821a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewForEachStatement(mode, labels, pos);
2822e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org        Target target(&this->target_stack_, loop);
282343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
282443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expression* enumerable = ParseExpression(true, CHECK_OK);
282543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expect(Token::RPAREN, CHECK_OK);
282643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
282743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Statement* body = ParseStatement(NULL, CHECK_OK);
28281fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org        InitializeForEachStatement(loop, expression, enumerable, body);
2829394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        top_scope_ = saved_scope;
2830394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope->set_end_position(scanner().location().end_pos);
2831394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope = for_scope->FinalizeBlockScope();
2832394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        ASSERT(for_scope == NULL);
283343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // Parsed for-in loop.
283443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return loop;
283543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
283643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
2837a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        init = factory()->NewExpressionStatement(
2838a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            expression, RelocInfo::kNoPosition);
283943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
284043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
284143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
284243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
284343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Standard 'for' loop
2844a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  ForStatement* loop = factory()->NewForStatement(labels, pos);
2845e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, loop);
284643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
284743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Parsed initializer at this point.
284843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SEMICOLON, CHECK_OK);
284943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
285043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* cond = NULL;
285143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() != Token::SEMICOLON) {
285243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    cond = ParseExpression(true, CHECK_OK);
285343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
285443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SEMICOLON, CHECK_OK);
285543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
285643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* next = NULL;
285743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() != Token::RPAREN) {
285843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* exp = ParseExpression(true, CHECK_OK);
2859a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition);
286043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
286143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
286243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
286343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* body = ParseStatement(NULL, CHECK_OK);
2864394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  top_scope_ = saved_scope;
2865394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  for_scope->set_end_position(scanner().location().end_pos);
2866394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  for_scope = for_scope->FinalizeBlockScope();
2867394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  if (for_scope != NULL) {
2868394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Rewrite a for statement of the form
2869394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //
2870394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //   for (let x = i; c; n) b
2871394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //
2872394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // into
2873394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //
2874394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //   {
2875394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //     let x = i;
2876394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //     for (; c; n) b
2877394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    //   }
2878394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ASSERT(init != NULL);
2879a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    Block* result = factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
2880400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org    result->AddStatement(init, zone());
2881400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org    result->AddStatement(loop, zone());
2882ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    result->set_scope(for_scope);
28831fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    loop->Initialize(NULL, cond, next, body);
2884394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    return result;
2885394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  } else {
28861fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    loop->Initialize(init, cond, next, body);
2887394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    return loop;
2888394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
288943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
289043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
289143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
289243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Precedence = 1
289343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseExpression(bool accept_IN, bool* ok) {
289443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Expression ::
289543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   AssignmentExpression
289643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Expression ',' AssignmentExpression
289743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
289843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
289943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() == Token::COMMA) {
290043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::COMMA, CHECK_OK);
2901a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int pos = position();
290243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2903a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
290443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
290543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
290643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
290743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
290843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
290943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Precedence = 2
291043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
291143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // AssignmentExpression ::
291243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ConditionalExpression
2913f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //   YieldExpression
291443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   LeftHandSideExpression AssignmentOperator AssignmentExpression
291543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2916f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  if (peek() == Token::YIELD && is_generator()) {
2917f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    return ParseYieldExpression(ok);
2918f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  }
2919f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org
292065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (fni_ != NULL) fni_->Enter();
292143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
292243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
292343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (!Token::IsAssignmentOp(peek())) {
292465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->Leave();
292543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Parsed conditional expression only (no assignment).
292643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return expression;
292743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
292843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2929c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Signal a reference error if the expression is an invalid left-hand
2930c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // side expression.  We could report this as a syntax error here but
2931c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // for compatibility with JSC we choose to report the error at
2932c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // runtime.
2933a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // TODO(ES5): Should change parsing for spec conformance.
293443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (expression == NULL || !expression->IsValidLeftHandSide()) {
2935dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    Handle<String> message =
29364a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        isolate()->factory()->invalid_lhs_in_assignment_string();
2937dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    expression = NewThrowReferenceError(message);
293843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
293943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29401b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (!top_scope_->is_classic_mode()) {
2941378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // Assignment to eval or arguments is disallowed in strict mode.
2942378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2943378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
294464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  MarkAsLValue(expression);
2945378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
294643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value op = Next();  // Get assignment operator.
2947a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
294843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
294943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
295043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // TODO(1231235): We try to estimate the set of properties set by
295143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // constructors. We define a new property whenever there is an
295243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // assignment to a property of 'this'. We should probably only add
295343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // properties if we haven't seen them before. Otherwise we'll
295443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // probably overestimate the number of properties.
295543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Property* property = expression ? expression->AsProperty() : NULL;
295643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (op == Token::ASSIGN &&
295743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      property != NULL &&
295843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      property->obj()->AsVariableProxy() != NULL &&
295943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      property->obj()->AsVariableProxy()->is_this()) {
2960c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    current_function_state_->AddProperty();
296143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
296243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
296321b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  // If we assign a function literal to a property we pretenure the
296421b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  // literal so it can be added as a constant function property.
296521b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  if (property != NULL && right->AsFunctionLiteral() != NULL) {
2966c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    right->AsFunctionLiteral()->set_pretenure();
296721b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  }
296821b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org
296965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (fni_ != NULL) {
297065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check if the right hand side is a call to avoid inferring a
297165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // name if we're dealing with "a = function(){...}();"-like
297265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // expression.
297365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if ((op == Token::INIT_VAR
297465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         || op == Token::INIT_CONST
297565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         || op == Token::ASSIGN)
297604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org        && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
297765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      fni_->Infer();
2978c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
2979c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      fni_->RemoveLastFunction();
298065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
298165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    fni_->Leave();
298265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
298365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2984b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  return factory()->NewAssignment(op, expression, right, pos);
298543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
298643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
298743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2988f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.orgExpression* Parser::ParseYieldExpression(bool* ok) {
2989f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  // YieldExpression ::
2990f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //   'yield' '*'? AssignmentExpression
2991a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
2992f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Expect(Token::YIELD, CHECK_OK);
299377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  Yield::Kind kind =
299477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
2995e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Expression* generator_object = factory()->NewVariableProxy(
2996e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      current_function_state_->generator_object_variable());
2997f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
2998a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Yield* yield = factory()->NewYield(generator_object, expression, kind, pos);
29994e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  if (kind == Yield::DELEGATING) {
30004e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    yield->set_index(current_function_state_->NextHandlerIndex());
30014e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  }
30024e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  return yield;
3003f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org}
3004f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org
3005f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org
300643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Precedence = 3
300743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
300843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ConditionalExpression ::
300943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   LogicalOrExpression
301043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
301143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3012a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
301343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // We start using the binary expression parser for prec >= 4 only!
301443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
301543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() != Token::CONDITIONAL) return expression;
301643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Consume(Token::CONDITIONAL);
301743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // In parsing the first assignment expression in conditional
301843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // expressions we always accept the 'in' keyword; see ECMA-262,
301943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // section 11.12, page 58.
302043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* left = ParseAssignmentExpression(true, CHECK_OK);
302143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::COLON, CHECK_OK);
302243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
3023a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewConditional(expression, left, right, pos);
302443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
302543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
302643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3027b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgint ParserBase::Precedence(Token::Value tok, bool accept_IN) {
302843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (tok == Token::IN && !accept_IN)
302943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return 0;  // 0 precedence will terminate binary expression parsing
303043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
303143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return Token::Precedence(tok);
303243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
303343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
303443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
303543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Precedence >= 4
303643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
303743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(prec >= 4);
303843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* x = ParseUnaryExpression(CHECK_OK);
303943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
304043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // prec1 >= 4
304143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    while (Precedence(peek(), accept_IN) == prec1) {
304243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Token::Value op = Next();
3043a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      int pos = position();
304443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
304543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
304643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // Compute some expressions involving only number literals.
30471510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      if (x && x->AsLiteral() && x->AsLiteral()->value()->IsNumber() &&
30481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org          y && y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) {
30491510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        double x_val = x->AsLiteral()->value()->Number();
30501510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        double y_val = y->AsLiteral()->value()->Number();
305143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
305243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        switch (op) {
305343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::ADD:
3054a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(x_val + y_val, pos);
305543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
305643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::SUB:
3057a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(x_val - y_val, pos);
305843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
305943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::MUL:
3060a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(x_val * y_val, pos);
306143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
306243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::DIV:
3063a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(x_val / y_val, pos);
306443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
3065b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org          case Token::BIT_OR: {
3066b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
3067a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(value, pos);
306843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
3069b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org          }
3070b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org          case Token::BIT_AND: {
3071b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
3072a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(value, pos);
307343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
3074b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org          }
3075b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org          case Token::BIT_XOR: {
3076b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
3077a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(value, pos);
307843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
3079b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org          }
308043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::SHL: {
308143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
3082a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(value, pos);
308343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
308443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
308543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::SHR: {
308643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
308743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            uint32_t value = DoubleToUint32(x_val) >> shift;
3088a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(value, pos);
308943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
309043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
309143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::SAR: {
309243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
309343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
3094a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            x = factory()->NewNumberLiteral(value, pos);
309543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            continue;
309643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
309743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          default:
309843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            break;
309943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
310043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
310143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
310243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // For now we distinguish between comparisons and other binary
310343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // operations.  (We could combine the two and get rid of this
310465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      // code and AST node eventually.)
310543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (Token::IsCompareOp(op)) {
310643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // We have a comparison.
310743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Token::Value cmp = op;
310843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        switch (op) {
310943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::NE: cmp = Token::EQ; break;
311043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
311143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          default: break;
311243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
3113a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        x = factory()->NewCompareOperation(cmp, x, y, pos);
311443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (cmp != op) {
311543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          // The comparison was negated - add a NOT.
3116a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          x = factory()->NewUnaryOperation(Token::NOT, x, pos);
311743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
311843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
311943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
312043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // We have a "normal" binary operation.
3121a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        x = factory()->NewBinaryOperation(op, x, y, pos);
312243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
312343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
312443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
312543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return x;
312643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
312743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
312843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
312943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseUnaryExpression(bool* ok) {
313043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // UnaryExpression ::
313143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   PostfixExpression
313243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'delete' UnaryExpression
313343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'void' UnaryExpression
313443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'typeof' UnaryExpression
313543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '++' UnaryExpression
313643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '--' UnaryExpression
313743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '+' UnaryExpression
313843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '-' UnaryExpression
313943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '~' UnaryExpression
314043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '!' UnaryExpression
314143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
314243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value op = peek();
314343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (Token::IsUnaryOp(op)) {
314443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    op = Next();
3145a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int pos = position();
3146c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    Expression* expression = ParseUnaryExpression(CHECK_OK);
314743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
31487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    if (expression != NULL && (expression->AsLiteral() != NULL)) {
31491510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      Handle<Object> literal = expression->AsLiteral()->value();
31507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      if (op == Token::NOT) {
31517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        // Convert the literal to a boolean condition and negate it.
31529faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        bool condition = literal->BooleanValue();
3153fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org        Handle<Object> result = isolate()->factory()->ToBoolean(!condition);
3154a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        return factory()->NewLiteral(result, pos);
31557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      } else if (literal->IsNumber()) {
31567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        // Compute some expressions involving only number literals.
31577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        double value = literal->Number();
31587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        switch (op) {
31597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org          case Token::ADD:
31607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org            return expression;
31617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org          case Token::SUB:
3162a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            return factory()->NewNumberLiteral(-value, pos);
31637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org          case Token::BIT_NOT:
3164a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            return factory()->NewNumberLiteral(~DoubleToInt32(value), pos);
31657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org          default:
31667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org            break;
31677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        }
316843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
316943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
317043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
317149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    // "delete identifier" is a syntax error in strict mode.
31721b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (op == Token::DELETE && !top_scope_->is_classic_mode()) {
317349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      VariableProxy* operand = expression->AsVariableProxy();
317449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      if (operand != NULL && !operand->is_this()) {
317549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        ReportMessage("strict_delete", Vector<const char*>::empty());
317649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        *ok = false;
317749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        return NULL;
317849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      }
317949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    }
318049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
3181b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org    // Desugar '+foo' into 'foo*1', this enables the collection of type feedback
3182b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org    // without any special stub and the multiplication is removed later in
3183b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org    // Crankshaft's canonicalization pass.
3184b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org    if (op == Token::ADD) {
3185b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org      return factory()->NewBinaryOperation(Token::MUL,
3186b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org                                           expression,
3187a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                           factory()->NewNumberLiteral(1, pos),
3188a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                           pos);
3189b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org    }
3190594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    // The same idea for '-foo' => 'foo*(-1)'.
3191594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    if (op == Token::SUB) {
3192594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      return factory()->NewBinaryOperation(Token::MUL,
3193594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org                                           expression,
3194a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                           factory()->NewNumberLiteral(-1, pos),
3195a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                           pos);
3196594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    }
3197594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    // ...and one more time for '~foo' => 'foo^(~0)'.
3198594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    if (op == Token::BIT_NOT) {
3199594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      return factory()->NewBinaryOperation(Token::BIT_XOR,
3200594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org                                           expression,
3201a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                           factory()->NewNumberLiteral(~0, pos),
3202a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                           pos);
3203594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    }
3204b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org
3205a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewUnaryOperation(op, expression, pos);
320643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
320743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else if (Token::IsCountOp(op)) {
320843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    op = Next();
3209c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    Expression* expression = ParseUnaryExpression(CHECK_OK);
3210c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // Signal a reference error if the expression is an invalid
3211c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // left-hand side expression.  We could report this as a syntax
3212c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // error here but for compatibility with JSC we choose to report the
3213c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // error at runtime.
3214c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    if (expression == NULL || !expression->IsValidLeftHandSide()) {
3215dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      Handle<String> message =
32164a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org          isolate()->factory()->invalid_lhs_in_prefix_op_string();
3217dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      expression = NewThrowReferenceError(message);
321843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
3219378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
32201b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (!top_scope_->is_classic_mode()) {
3221378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Prefix expression operand in strict mode may not be eval or arguments.
3222378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
3223378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    }
322464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    MarkAsLValue(expression);
3225378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
3226b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    return factory()->NewCountOperation(op,
3227b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                        true /* prefix */,
3228b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                        expression,
3229a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                        position());
323043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
323143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
323243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return ParsePostfixExpression(ok);
323343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
323443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
323543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
323643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
323743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParsePostfixExpression(bool* ok) {
323843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // PostfixExpression ::
323943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   LeftHandSideExpression ('++' | '--')?
324043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3241c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
3242df8c03c138809b385f3cca5d424d7b2f8ad92527whesse@chromium.org  if (!scanner().HasAnyLineTerminatorBeforeNext() &&
32435f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org      Token::IsCountOp(peek())) {
3244c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // Signal a reference error if the expression is an invalid
3245c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // left-hand side expression.  We could report this as a syntax
3246c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // error here but for compatibility with JSC we choose to report the
3247c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // error at runtime.
3248c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    if (expression == NULL || !expression->IsValidLeftHandSide()) {
3249dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      Handle<String> message =
32504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org          isolate()->factory()->invalid_lhs_in_postfix_op_string();
3251dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      expression = NewThrowReferenceError(message);
325243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
3253378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
32541b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (!top_scope_->is_classic_mode()) {
3255378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Postfix expression operand in strict mode may not be eval or arguments.
3256378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
3257378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    }
325864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    MarkAsLValue(expression);
3259378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
326043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Token::Value next = Next();
3261c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    expression =
3262b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        factory()->NewCountOperation(next,
3263b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                     false /* postfix */,
3264b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                     expression,
3265a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                     position());
326643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
3267c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  return expression;
326843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
326943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
327043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
327143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseLeftHandSideExpression(bool* ok) {
327243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // LeftHandSideExpression ::
327343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   (NewExpression | MemberExpression) ...
327443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
327543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* result;
327643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::NEW) {
327743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    result = ParseNewExpression(CHECK_OK);
327843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
327943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    result = ParseMemberExpression(CHECK_OK);
328043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
328143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
328243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (true) {
328343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    switch (peek()) {
328443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::LBRACK: {
328543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Consume(Token::LBRACK);
3286a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        int pos = position();
328743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expression* index = ParseExpression(true, CHECK_OK);
3288b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        result = factory()->NewProperty(result, index, pos);
328943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expect(Token::RBRACK, CHECK_OK);
329043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
329143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
329243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
329343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::LPAREN: {
3294f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com        int pos;
3295f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com        if (scanner().current_token() == Token::IDENTIFIER) {
3296f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com          // For call of an identifier we want to report position of
3297f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com          // the identifier as position of the call in the stack trace.
3298a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          pos = position();
3299f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com        } else {
3300f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com          // For other kinds of calls we record position of the parenthesis as
3301f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com          // position of the call.  Note that this is extremely important for
3302f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com          // expressions of the form function(){...}() for which call position
3303f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com          // should not point to the closing brace otherwise it will intersect
3304f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com          // with positions recorded for function literal and confuse debugger.
3305a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          pos = peek_position();
3306de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org          // Also the trailing parenthesis are a hint that the function will
3307de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org          // be called immediately. If we happen to have parsed a preceding
3308de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org          // function literal eagerly, we can also compile it eagerly.
3309de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org          if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
3310de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org            result->AsFunctionLiteral()->set_parenthesized();
3311de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org          }
3312f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com        }
331343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
331443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
331543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // Keep track of eval() calls since they disable all local variable
3316a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // optimizations.
3317a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // The calls that need special treatment are the
3318c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        // direct eval calls. These calls are all of the form eval(...), with
3319c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        // no explicit receiver.
3320c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org        // These calls are marked as potentially direct eval calls. Whether
3321c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org        // they are actually direct calls to eval is determined at run time.
3322fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org        VariableProxy* callee = result->AsVariableProxy();
3323ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        if (callee != NULL &&
33244a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org            callee->IsVariable(isolate()->factory()->eval_string())) {
3325c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          top_scope_->DeclarationScope()->RecordEvalCall();
332643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
3327b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        result = factory()->NewCall(result, args, pos);
332879e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org        if (fni_ != NULL) fni_->RemoveLastFunction();
332943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
333043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
333143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
333243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::PERIOD: {
333343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Consume(Token::PERIOD);
3334a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        int pos = position();
3335d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org        Handle<String> name = ParseIdentifierName(CHECK_OK);
3336a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        result = factory()->NewProperty(
3337a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            result, factory()->NewLiteral(name, pos), pos);
333865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        if (fni_ != NULL) fni_->PushLiteralName(name);
333943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
334043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
334143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
334243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      default:
334343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return result;
334443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
334543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
334643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
334743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
334843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3349b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgExpression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
335043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // NewExpression ::
335143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ('new')+ MemberExpression
335243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
335343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // The grammar for new expressions is pretty warped. The keyword
335443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // 'new' can either be a part of the new expression (where it isn't
335543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // followed by an argument list) or a part of the member expression,
335643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // where it must be followed by an argument list. To accommodate
335743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // this, we parse the 'new' keywords greedily and keep track of how
335843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // many we have parsed. This information is then passed on to the
335943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // member expression parser, which is only allowed to match argument
336043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // lists as long as it has 'new' prefixes left
3361b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Expect(Token::NEW, CHECK_OK);
3362a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  PositionStack::Element pos(stack, position());
3363b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
3364b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Expression* result;
3365b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  if (peek() == Token::NEW) {
3366b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    result = ParseNewPrefix(stack, CHECK_OK);
3367b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  } else {
3368b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
336943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
337043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3371b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  if (!stack->is_empty()) {
3372b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    int last = stack->pop();
3373b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    result = factory()->NewCallNew(
33747028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        result, new(zone()) ZoneList<Expression*>(0, zone()), last);
337543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
337643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
337743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
337843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
337943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3380b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgExpression* Parser::ParseNewExpression(bool* ok) {
3381b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  PositionStack stack(ok);
3382b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  return ParseNewPrefix(&stack, ok);
3383b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
3384b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
3385b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
338643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseMemberExpression(bool* ok) {
3387b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  return ParseMemberWithNewPrefixesExpression(NULL, ok);
338843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
338943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
339043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3391b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgExpression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
3392b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org                                                         bool* ok) {
339343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // MemberExpression ::
339443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   (PrimaryExpression | FunctionLiteral)
339543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //     ('[' Expression ']' | '.' Identifier | Arguments)*
339643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
339743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Parse the initial primary or function expression.
339843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* result = NULL;
339943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::FUNCTION) {
340043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::FUNCTION, CHECK_OK);
3401a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int function_token_position = position();
3402e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    bool is_generator = allow_generators() && Check(Token::MUL);
340343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Handle<String> name;
340404921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org    bool is_strict_reserved_name = false;
340583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    if (peek_any_identifier()) {
340604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
340704921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org                                                 CHECK_OK);
340883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    }
3409dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    FunctionLiteral::FunctionType function_type = name.is_null()
34107c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org        ? FunctionLiteral::ANONYMOUS_EXPRESSION
34117c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org        : FunctionLiteral::NAMED_EXPRESSION;
34127c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org    result = ParseFunctionLiteral(name,
34137c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                  is_strict_reserved_name,
3414f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                                  is_generator,
34157c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                  function_token_position,
3416dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                                  function_type,
34177c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                  CHECK_OK);
341843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
341943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    result = ParsePrimaryExpression(CHECK_OK);
342043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
342143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
342243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (true) {
342343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    switch (peek()) {
342443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::LBRACK: {
342543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Consume(Token::LBRACK);
3426a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        int pos = position();
342743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expression* index = ParseExpression(true, CHECK_OK);
3428b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        result = factory()->NewProperty(result, index, pos);
342904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org        if (fni_ != NULL) {
343004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org          if (index->IsPropertyName()) {
343104921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org            fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
343204921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org          } else {
343304921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org            fni_->PushLiteralName(
34344a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                isolate()->factory()->anonymous_function_string());
343504921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org          }
343604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org        }
343743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expect(Token::RBRACK, CHECK_OK);
343843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
343943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
344043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::PERIOD: {
344143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Consume(Token::PERIOD);
3442a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        int pos = position();
3443d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org        Handle<String> name = ParseIdentifierName(CHECK_OK);
3444a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        result = factory()->NewProperty(
3445a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            result, factory()->NewLiteral(name, pos), pos);
344665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        if (fni_ != NULL) fni_->PushLiteralName(name);
344743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
344843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
344943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::LPAREN: {
3450b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org        if ((stack == NULL) || stack->is_empty()) return result;
345143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // Consume one of the new prefixes (already parsed).
345243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3453a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        int pos = stack->pop();
3454a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        result = factory()->NewCallNew(result, args, pos);
345543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
345643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
345743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      default:
345843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return result;
345943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
346043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
346143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
346243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
346343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
346443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenDebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
346543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
346643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // contexts this is used as a statement which invokes the debugger as i a
346743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // break point is present.
346843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // DebuggerStatement ::
346943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'debugger' ';'
347043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3471a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
347243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::DEBUGGER, CHECK_OK);
347343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
3474a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewDebuggerStatement(pos);
347543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
347643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
347743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
347843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Parser::ReportUnexpectedToken(Token::Value token) {
347943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // We don't report stack overflows here, to avoid increasing the
348043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // stack depth even further.  Instead we report it after parsing is
3481b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // over, in ParseProgram/ParseJson.
3482a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  if (token == Token::ILLEGAL && stack_overflow()) return;
348343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Four of the tokens are treated specially
348443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (token) {
3485a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case Token::EOS:
3486a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      return ReportMessage("unexpected_eos", Vector<const char*>::empty());
3487a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case Token::NUMBER:
3488a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      return ReportMessage("unexpected_token_number",
3489a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                           Vector<const char*>::empty());
3490a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case Token::STRING:
3491a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      return ReportMessage("unexpected_token_string",
3492a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                           Vector<const char*>::empty());
3493a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case Token::IDENTIFIER:
3494a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      return ReportMessage("unexpected_token_identifier",
3495a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                           Vector<const char*>::empty());
349683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::FUTURE_RESERVED_WORD:
349704921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      return ReportMessage("unexpected_reserved",
349804921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org                           Vector<const char*>::empty());
3499f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    case Token::YIELD:
350004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org    case Token::FUTURE_STRICT_RESERVED_WORD:
35011b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      return ReportMessage(top_scope_->is_classic_mode() ?
35021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                               "unexpected_token_identifier" :
35031b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                               "unexpected_strict_reserved",
350483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org                           Vector<const char*>::empty());
3505a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    default:
3506a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      const char* name = Token::String(token);
3507a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      ASSERT(name != NULL);
3508a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
350943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
351043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
351143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
351243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35134a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.comvoid Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
351483e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
35154a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com  const char* element[1] = { *name_string };
35164a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com  ReportMessage("invalid_preparser_data",
35174a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com                Vector<const char*>(element, 1));
35184a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com  *ok = false;
35194a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com}
35204a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com
35214a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com
352243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParsePrimaryExpression(bool* ok) {
352343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // PrimaryExpression ::
352443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'this'
352543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'null'
352643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'true'
352743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'false'
352843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Identifier
352943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Number
353043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   String
353143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ArrayLiteral
353243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ObjectLiteral
353343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   RegExpLiteral
353443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '(' Expression ')'
353543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3536a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
353743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* result = NULL;
353843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (peek()) {
353943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::THIS: {
354043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Consume(Token::THIS);
3541b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      result = factory()->NewVariableProxy(top_scope_->receiver());
354243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
354343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
354443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
354543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::NULL_LITERAL:
354643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Consume(Token::NULL_LITERAL);
3547a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      result = factory()->NewLiteral(isolate()->factory()->null_value(), pos);
354843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
354943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
355043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::TRUE_LITERAL:
355143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Consume(Token::TRUE_LITERAL);
3552a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      result = factory()->NewLiteral(isolate()->factory()->true_value(), pos);
355343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
355443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
355543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::FALSE_LITERAL:
355643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Consume(Token::FALSE_LITERAL);
3557a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      result = factory()->NewLiteral(isolate()->factory()->false_value(), pos);
355843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
355943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
356083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::IDENTIFIER:
3561f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    case Token::YIELD:
356204921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org    case Token::FUTURE_STRICT_RESERVED_WORD: {
356343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Handle<String> name = ParseIdentifier(CHECK_OK);
356465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      if (fni_ != NULL) fni_->PushVariableName(name);
3565bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      // The name may refer to a module instance object, so its type is unknown.
3566bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
3567bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (FLAG_print_interface_details)
3568bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("# Variable %s ", name->ToAsciiArray());
3569bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
35707028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      Interface* interface = Interface::NewUnknown(zone());
3571a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      result = top_scope_->NewUnresolved(factory(), name, interface, pos);
357243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
357343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
357443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
357543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::NUMBER: {
357643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Consume(Token::NUMBER);
35779e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org      ASSERT(scanner().is_literal_ascii());
3578a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      double value = StringToDouble(isolate()->unicode_cache(),
3579a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org                                    scanner().literal_ascii_string(),
3580ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                    ALLOW_HEX | ALLOW_OCTAL |
3581ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                        ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
3582a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      result = factory()->NewNumberLiteral(value, pos);
358343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
358443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
358543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
358643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::STRING: {
358743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Consume(Token::STRING);
3588bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      Handle<String> symbol = GetSymbol();
3589a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      result = factory()->NewLiteral(symbol, pos);
359065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      if (fni_ != NULL) fni_->PushLiteralName(symbol);
359143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
359243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
359343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
359443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::ASSIGN_DIV:
359543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      result = ParseRegExpLiteral(true, CHECK_OK);
359643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
359743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
359843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::DIV:
359943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      result = ParseRegExpLiteral(false, CHECK_OK);
360043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
360143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
360243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::LBRACK:
360343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      result = ParseArrayLiteral(CHECK_OK);
360443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
360543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
360643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::LBRACE:
360743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      result = ParseObjectLiteral(CHECK_OK);
360843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
360943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
361043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::LPAREN:
361143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Consume(Token::LPAREN);
3612c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      // Heuristically try to detect immediately called functions before
3613c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      // seeing the call parentheses.
3614c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      parenthesized_function_ = (peek() == Token::FUNCTION);
361543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      result = ParseExpression(true, CHECK_OK);
361643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expect(Token::RPAREN, CHECK_OK);
361743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
361843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
361943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::MOD:
3620e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      if (allow_natives_syntax() || extension_ != NULL) {
362143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        result = ParseV8Intrinsic(CHECK_OK);
362243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
362343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
362443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // If we're not allowing special syntax we fall-through to the
362543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // default case.
362643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
362743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default: {
3628c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org      Token::Value tok = Next();
362943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      ReportUnexpectedToken(tok);
363043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      *ok = false;
363143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return NULL;
363243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
363343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
363443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
363543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
363643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
363743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
363843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
363943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseArrayLiteral(bool* ok) {
364043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ArrayLiteral ::
364143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '[' Expression? (',' Expression?)* ']'
364243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3643a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
36447028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4, zone());
364543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LBRACK, CHECK_OK);
364643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::RBRACK) {
364743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* elem;
364843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (peek() == Token::COMMA) {
3649a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      elem = GetLiteralTheHole(peek_position());
365043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
365143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      elem = ParseAssignmentExpression(true, CHECK_OK);
365243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
36537028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    values->Add(elem, zone());
365443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (peek() != Token::RBRACK) {
365543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expect(Token::COMMA, CHECK_OK);
365643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
365743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
365843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RBRACK, CHECK_OK);
36599a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
36609a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  // Update the scope information before the pre-parsing bailout.
3661c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
36629a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
3663e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  return factory()->NewArrayLiteral(values, literal_index, pos);
36649258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org}
36659258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
36669258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
3667bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgbool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
3668a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  if (expression->AsLiteral() != NULL) return true;
3669bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3670bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  return lit != NULL && lit->is_simple();
3671bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3672bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
36730b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org
36743d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.orgHandle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
36753d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org                                              Expression* expression) {
36763d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  Factory* factory = isolate->factory();
3677bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  ASSERT(IsCompileTimeValue(expression));
3678d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
3679bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  ObjectLiteral* object_literal = expression->AsObjectLiteral();
3680bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  if (object_literal != NULL) {
3681bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    ASSERT(object_literal->is_simple());
3682f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    if (object_literal->fast_elements()) {
3683dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3684f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    } else {
3685dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3686f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    }
3687bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    result->set(kElementsSlot, *object_literal->constant_properties());
3688bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  } else {
3689bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    ArrayLiteral* array_literal = expression->AsArrayLiteral();
3690bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    ASSERT(array_literal != NULL && array_literal->is_simple());
3691dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
36920c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    result->set(kElementsSlot, *array_literal->constant_elements());
3693bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  }
3694bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  return result;
3695bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3696bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3697bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3698dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgCompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
3699dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    Handle<FixedArray> value) {
3700dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3701dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  return static_cast<LiteralType>(literal_type->value());
3702bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3703bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3704bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3705bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgHandle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3706bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3707bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3708bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3709bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
371043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseObjectLiteral(bool* ok) {
371143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ObjectLiteral ::
371243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '{' (
3713d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org  //       ((IdentifierName | String | Number) ':' AssignmentExpression)
3714d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org  //     | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
371543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //    )*[','] '}'
371643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3717a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
3718fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  ZoneList<ObjectLiteral::Property*>* properties =
37197028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
37209258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  int number_of_boilerplate_properties = 0;
3721ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  bool has_function = false;
372243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3723b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  ObjectLiteralChecker checker(this, top_scope_->language_mode());
3724378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
372543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LBRACE, CHECK_OK);
3726378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
372743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::RBRACE) {
372865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->Enter();
372965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
373043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Literal* key = NULL;
3731d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org    Token::Value next = peek();
3732a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int next_pos = peek_position();
3733378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
3734d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org    switch (next) {
373583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      case Token::FUTURE_RESERVED_WORD:
373604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      case Token::FUTURE_STRICT_RESERVED_WORD:
373743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::IDENTIFIER: {
373843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        bool is_getter = false;
373943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        bool is_setter = false;
374043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Handle<String> id =
374104921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org            ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
374265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        if (fni_ != NULL) fni_->PushLiteralName(id);
374365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3744c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org        if ((is_getter || is_setter) && peek() != Token::COLON) {
3745dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          // Special handling of getter and setter syntax:
3746dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3747dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          // We have already read the "get" or "set" keyword.
3748dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          Token::Value next = Next();
3749dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          bool is_keyword = Token::IsKeyword(next);
3750dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          if (next != i::Token::IDENTIFIER &&
3751dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              next != i::Token::FUTURE_RESERVED_WORD &&
3752dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
3753dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              next != i::Token::NUMBER &&
3754dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              next != i::Token::STRING &&
3755dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              !is_keyword) {
3756dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org            // Unexpected token.
3757dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org            ReportUnexpectedToken(next);
3758dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org            *ok = false;
3759dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org            return NULL;
3760dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          }
3761dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          // Validate the property.
3762dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
3763dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          checker.CheckProperty(next, type, CHECK_OK);
3764dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          Handle<String> name = is_keyword
3765dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              ? isolate_->factory()->InternalizeUtf8String(Token::String(next))
3766dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              : GetSymbol();
3767dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          FunctionLiteral* value =
3768dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org              ParseFunctionLiteral(name,
3769dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org                                   false,   // reserved words are allowed here
3770dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org                                   false,   // not a generator
3771dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org                                   RelocInfo::kNoPosition,
3772dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org                                   FunctionLiteral::ANONYMOUS_EXPRESSION,
3773dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org                                   CHECK_OK);
3774dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          // Allow any number of parameters for compatibilty with JSC.
3775dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          // Specification only allows zero parameters for get and one for set.
3776dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          ObjectLiteral::Property* property =
3777a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org              factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
3778e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          if (ObjectLiteral::IsBoilerplateProperty(property)) {
3779dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org            number_of_boilerplate_properties++;
3780dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          }
3781dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          properties->Add(property, zone());
3782dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
3783dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org
3784dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          if (fni_ != NULL) {
3785dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org            fni_->Infer();
3786dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org            fni_->Leave();
3787dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          }
3788dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org          continue;  // restart the while
378943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
3790c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org        // Failed to parse as get/set property, so it's just a property
3791c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org        // called "get" or "set".
3792a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        key = factory()->NewLiteral(id, next_pos);
379343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
379443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
379543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::STRING: {
3796c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org        Consume(Token::STRING);
3797bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org        Handle<String> string = GetSymbol();
379865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        if (fni_ != NULL) fni_->PushLiteralName(string);
379943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        uint32_t index;
380026c16f8ef35ec25d36420512a4ceaa74ea2e2b05vegorov@chromium.org        if (!string.is_null() && string->AsArrayIndex(&index)) {
3801a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          key = factory()->NewNumberLiteral(index, next_pos);
3802c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org          break;
380343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
3804a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        key = factory()->NewLiteral(string, next_pos);
380543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
380643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
380743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case Token::NUMBER: {
380843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Consume(Token::NUMBER);
38099e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org        ASSERT(scanner().is_literal_ascii());
3810a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        double value = StringToDouble(isolate()->unicode_cache(),
3811a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org                                      scanner().literal_ascii_string(),
3812ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                      ALLOW_HEX | ALLOW_OCTAL |
3813ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                          ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
3814a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        key = factory()->NewNumberLiteral(value, next_pos);
381543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
381643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
381743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      default:
3818c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org        if (Token::IsKeyword(next)) {
3819c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org          Consume(next);
3820bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org          Handle<String> string = GetSymbol();
3821a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          key = factory()->NewLiteral(string, next_pos);
3822c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org        } else {
3823c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org          // Unexpected token.
3824c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org          Token::Value next = Next();
3825c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org          ReportUnexpectedToken(next);
3826c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org          *ok = false;
3827c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org          return NULL;
3828c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org        }
382943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
383043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3831dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org    // Validate the property
3832dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org    checker.CheckProperty(next, kValueProperty, CHECK_OK);
3833dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org
383443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::COLON, CHECK_OK);
383543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* value = ParseAssignmentExpression(true, CHECK_OK);
383643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
383743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ObjectLiteral::Property* property =
3838812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        new(zone()) ObjectLiteral::Property(key, value, isolate());
38399258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
3840ecb9dd69014d1d8aad1a08bd8b593fbf94107324svenpanne@chromium.org    // Mark top-level object literals that contain function literals and
3841ecb9dd69014d1d8aad1a08bd8b593fbf94107324svenpanne@chromium.org    // pretenure the literal so it can be added as a constant function
3842ecb9dd69014d1d8aad1a08bd8b593fbf94107324svenpanne@chromium.org    // property.
3843ecb9dd69014d1d8aad1a08bd8b593fbf94107324svenpanne@chromium.org    if (top_scope_->DeclarationScope()->is_global_scope() &&
3844ecb9dd69014d1d8aad1a08bd8b593fbf94107324svenpanne@chromium.org        value->AsFunctionLiteral() != NULL) {
3845ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      has_function = true;
3846c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      value->AsFunctionLiteral()->set_pretenure();
3847ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    }
3848ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
38499258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3850e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    if (ObjectLiteral::IsBoilerplateProperty(property)) {
3851e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      number_of_boilerplate_properties++;
3852e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    }
38537028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    properties->Add(property, zone());
385443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
385543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // TODO(1240767): Consider allowing trailing comma.
385643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
385765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
385865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) {
385965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      fni_->Infer();
386065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      fni_->Leave();
386165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
386243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
386343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RBRACE, CHECK_OK);
3864378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
386543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Computation of literal_index must happen before pre parse bailout.
3866c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
386743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3868e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  return factory()->NewObjectLiteral(properties,
3869b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                     literal_index,
3870e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org                                     number_of_boilerplate_properties,
3871a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                     has_function,
3872a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                     pos);
387343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
387443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
387543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
387643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
3877a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
38785f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  if (!scanner().ScanRegExpPattern(seen_equal)) {
387943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Next();
388043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ReportMessage("unterminated_regexp", Vector<const char*>::empty());
388143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *ok = false;
388243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return NULL;
388343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
388443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3885c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
388643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
38879e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  Handle<String> js_pattern = NextLiteralString(TENURED);
38885f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  scanner().ScanRegExpFlags();
38899e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  Handle<String> js_flags = NextLiteralString(TENURED);
389043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Next();
389143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3892a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
389343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
389443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
389543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
389643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
389743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Arguments ::
389843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '(' (AssignmentExpression)*[','] ')'
389943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
39007028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4, zone());
390143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
390243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool done = (peek() == Token::RPAREN);
390343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (!done) {
390443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
39057028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    result->Add(argument, zone());
3906876cca833d7212e476250d102cad185cdcfa9dfesvenpanne@chromium.org    if (result->length() > Code::kMaxArguments) {
3907e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org      ReportMessageAt(scanner().location(), "too_many_arguments",
3908e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org                      Vector<const char*>::empty());
3909e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org      *ok = false;
3910e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org      return NULL;
3911e297f5973a8a9ff0d9945da3f1e2d8a6230c294djkummerow@chromium.org    }
391243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    done = (peek() == Token::RPAREN);
391343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (!done) Expect(Token::COMMA, CHECK_OK);
391443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
391543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
3916fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  return result;
391743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
391843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
391943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
39201b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orgclass SingletonLogger : public ParserRecorder {
39211b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org public:
39221b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
3923b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  virtual ~SingletonLogger() { }
39241b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39251b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  void Reset() { has_error_ = false; }
39261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39271b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual void LogFunction(int start,
39281b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                           int end,
39291b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                           int literals,
39301b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                           int properties,
39311b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                           LanguageMode mode) {
39321b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    ASSERT(!has_error_);
39331b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    start_ = start;
39341b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    end_ = end;
39351b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    literals_ = literals;
39361b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    properties_ = properties;
39371b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    mode_ = mode;
39381b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  };
39391b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39401b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Logs a symbol creation of a literal or identifier.
39411b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
3942154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  virtual void LogUtf16Symbol(int start, Vector<const uc16> literal) { }
39431b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39441b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Logs an error message and marks the log as containing an error.
39451b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Further logging will be ignored, and ExtractData will return a vector
39461b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // representing the error only.
39471b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual void LogMessage(int start,
39481b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                          int end,
39491b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                          const char* message,
39501b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                          const char* argument_opt) {
3951657d53b99cb4d261f8245bcb4248c39eb0a2b10frossberg@chromium.org    if (has_error_) return;
39521b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    has_error_ = true;
39531b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    start_ = start;
39541b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    end_ = end;
39551b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    message_ = message;
39561b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    argument_opt_ = argument_opt;
39571b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
39581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39591b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual int function_position() { return 0; }
39601b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39611b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual int symbol_position() { return 0; }
39621b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39631b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual int symbol_ids() { return -1; }
39641b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39651b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual Vector<unsigned> ExtractData() {
39661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    UNREACHABLE();
39671b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    return Vector<unsigned>();
39681b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
39691b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39701b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual void PauseRecording() { }
39711b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39721b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  virtual void ResumeRecording() { }
39731b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39741b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  bool has_error() { return has_error_; }
39751b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39761b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int start() { return start_; }
39771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int end() { return end_; }
39781b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int literals() {
39791b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    ASSERT(!has_error_);
39801b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    return literals_;
39811b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
39821b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int properties() {
39831b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    ASSERT(!has_error_);
39841b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    return properties_;
39851b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
39861b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  LanguageMode language_mode() {
39871b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    ASSERT(!has_error_);
39881b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    return mode_;
39891b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
39901b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  const char* message() {
39911b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    ASSERT(has_error_);
39921b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    return message_;
39931b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
39941b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  const char* argument_opt() {
39951b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    ASSERT(has_error_);
39961b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    return argument_opt_;
39971b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
39981b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
39991b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org private:
40001b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  bool has_error_;
40011b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int start_;
40021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int end_;
40031b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // For function entries.
40041b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int literals_;
40051b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int properties_;
40061b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  LanguageMode mode_;
40071b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // For error messages.
40081b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  const char* message_;
40091b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  const char* argument_opt_;
40101b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org};
40111b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
40121b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
4013dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgFunctionLiteral* Parser::ParseFunctionLiteral(
4014dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    Handle<String> function_name,
4015dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    bool name_is_strict_reserved,
4016dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    bool is_generator,
4017a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int function_token_pos,
4018dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    FunctionLiteral::FunctionType function_type,
4019dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    bool* ok) {
402043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Function ::
402143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
402243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4023a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = function_token_pos == RelocInfo::kNoPosition
4024a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      ? peek_position() : function_token_pos;
4025a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org
40267c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // Anonymous functions were passed either the empty symbol or a null
40277c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // handle as the function name.  Remember if we were passed a non-empty
40287c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // handle to decide whether to invoke function name inference.
40297c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  bool should_infer_name = function_name.is_null();
40307c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org
40317c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // We want a non-null handle as the function name.
40327c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  if (should_infer_name) {
40334a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    function_name = isolate()->factory()->empty_string();
403443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
403543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
403643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int num_parameters = 0;
4037b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // Function declarations are function scoped in normal mode, so they are
4038b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // hoisted. In harmony block scoping mode they are block scoped, so they
4039b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // are not hoisted.
40401e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //
40411e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // One tricky case are function declarations in a local sloppy-mode eval:
40421e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // their declaration is hoisted, but they still see the local scope. E.g.,
40431e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //
40441e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // function() {
40451e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   var x = 0
40461e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   try { throw 1 } catch (x) { eval("function g() { return x }") }
40471e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   return g()
40481e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // }
40491e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //
40501e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // needs to return 1. To distinguish such cases, we need to detect
40511e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // (1) whether a function stems from a sloppy eval, and
40521e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // (2) whether it actually hoists across the eval.
40531e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Unfortunately, we do not represent sloppy eval scopes, so we do not have
40541e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // either information available directly, especially not when lazily compiling
40551e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // a function like 'g'. We hence rely on the following invariants:
40561e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // - (1) is the case iff the innermost scope of the deserialized scope chain
40571e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   under which we compile is _not_ a declaration scope. This holds because
40581e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   in all normal cases, function declarations are fully hoisted to a
40591e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   declaration scope and compiled relative to that.
40601e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // - (2) is the case iff the current declaration scope is still the original
40611e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   one relative to the deserialized scope chain. Otherwise we must be
40621e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   compiling a function in an inner declaration scope in the eval, e.g. a
40631e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   nested function, and hoisting works normally relative to that.
40641e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Scope* declaration_scope = top_scope_->DeclarationScope();
40651e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Scope* original_declaration_scope = original_scope_->DeclarationScope();
4066dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  Scope* scope =
40671e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
40681e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      (original_scope_ == original_declaration_scope ||
40691e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org       declaration_scope != original_declaration_scope)
40701e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org          ? NewScope(declaration_scope, FUNCTION_SCOPE)
40711e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org          : NewScope(top_scope_, FUNCTION_SCOPE);
407204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  ZoneList<Statement*>* body = NULL;
40731b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int materialized_literal_count = -1;
40741b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int expected_property_count = -1;
407504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  int handler_count = 0;
407656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  FunctionLiteral::ParameterFlag duplicate_parameters =
407756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org      FunctionLiteral::kNoDuplicateParameters;
4078471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
4079471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      ? FunctionLiteral::kIsParenthesized
4080471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      : FunctionLiteral::kNotParenthesized;
4081f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  FunctionLiteral::IsGeneratorFlag generator = is_generator
4082f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      ? FunctionLiteral::kIsGenerator
4083f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      : FunctionLiteral::kNotGenerator;
4084b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  AstProperties ast_properties;
40852c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org  BailoutReason dont_optimize_reason = kNoReason;
408643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Parse function body.
4087e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  { FunctionState function_state(this, scope, isolate());
40887c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org    top_scope_->SetScopeName(function_name);
408943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4090e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (is_generator) {
4091e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // For generators, allocating variables in contexts is currently a win
4092e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // because it minimizes the work needed to suspend and resume an
4093e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // activation.
4094e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      top_scope_->ForceContextAllocation();
4095e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
4096e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // Calling a generator returns a generator object.  That object is stored
4097e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // in a temporary variable, a definition that is used by "yield"
4098e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // expressions.  Presence of a variable for the generator object in the
4099e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // FunctionState indicates that this function is a generator.
4100e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      Variable* temp = top_scope_->DeclarationScope()->NewTemporary(
4101e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          isolate()->factory()->dot_generator_object_string());
4102e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      function_state.set_generator_object_variable(temp);
4103e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    }
4104e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
410543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //  FormalParameterList ::
410643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //    '(' (Identifier)*[','] ')'
410743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::LPAREN, CHECK_OK);
4108394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    scope->set_start_position(scanner().location().beg_pos);
41091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Scanner::Location name_loc = Scanner::Location::invalid();
41101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Scanner::Location dupe_loc = Scanner::Location::invalid();
41111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Scanner::Location reserved_loc = Scanner::Location::invalid();
41120a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
411343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    bool done = (peek() == Token::RPAREN);
411443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    while (!done) {
411504921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      bool is_strict_reserved = false;
411683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      Handle<String> param_name =
41170cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org          ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
4118378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
4119378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Store locations for possible future error reports.
4120378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
4121378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        name_loc = scanner().location();
4122378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      }
4123378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
412456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
4125378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        dupe_loc = scanner().location();
4126378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      }
412704921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      if (!reserved_loc.IsValid() && is_strict_reserved) {
412883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        reserved_loc = scanner().location();
412983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
4130378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
413156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org      top_scope_->DeclareParameter(param_name, VAR);
4132fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      num_parameters++;
4133876cca833d7212e476250d102cad185cdcfa9dfesvenpanne@chromium.org      if (num_parameters > Code::kMaxArguments) {
4134d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com        ReportMessageAt(scanner().location(), "too_many_parameters",
4135d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com                        Vector<const char*>::empty());
4136d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com        *ok = false;
4137d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com        return NULL;
4138d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com      }
413943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      done = (peek() == Token::RPAREN);
414043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (!done) Expect(Token::COMMA, CHECK_OK);
414143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
414243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::RPAREN, CHECK_OK);
414343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
414443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::LBRACE, CHECK_OK);
414543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
414643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If we have a named function expression, we add a local variable
414743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration to the body of the function with the name of the
414843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // function and let it refer to the function itself (closure).
414943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // NOTE: We create a proxy and resolve it here so that in the
415043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // future we can change the AST to only refer to VariableProxies
415143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // instead of Variables and Proxis as is the case now.
415204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    Variable* fvar = NULL;
415304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    Token::Value fvar_init_op = Token::INIT_CONST;
4154dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
4155ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
4156ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
4157ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      fvar = new(zone()) Variable(top_scope_,
4158ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com         function_name, fvar_mode, true /* is valid LHS */,
415928583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org         Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
4160ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      VariableProxy* proxy = factory()->NewVariableProxy(fvar);
4161a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
4162a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          proxy, fvar_mode, top_scope_, RelocInfo::kNoPosition);
4163ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      top_scope_->DeclareFunctionVar(fvar_declaration);
416443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
416543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
41661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // Determine whether the function will be lazily compiled.
41671b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // The heuristics are:
41681b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // - It must not have been prohibited by the caller to Parse (some callers
41691b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   need a full AST).
41709c741c80bfc8026103e86b46e15e2544095ce67eyangguo@chromium.org    // - The outer scope must allow lazy compilation of inner functions.
41711b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // - The function mustn't be a function expression with an open parenthesis
41721b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   before; we consider that a hint that the function will be called
41731b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   immediately, and it would be a waste of time to make it lazily
41741b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   compiled.
41751b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // These are all things we can know at this point, without looking at the
41761b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // function itself.
4177c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
41789c741c80bfc8026103e86b46e15e2544095ce67eyangguo@chromium.org                               top_scope_->AllowsLazyCompilation() &&
41791b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                               !parenthesized_function_);
4180c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    parenthesized_function_ = false;  // The bit was set for this function only.
418143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4182d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org    if (is_lazily_compiled) {
4183a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      int function_block_pos = position();
41841b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      FunctionEntry entry;
4185e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      if (pre_parse_data_ != NULL) {
4186e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        // If we have pre_parse_data_, we use it to skip parsing the function
4187e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        // body.  The preparser data contains the information we need to
4188e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        // construct the lazy function.
4189e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        entry = pre_parse_data()->GetFunctionEntry(function_block_pos);
41901b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        if (entry.is_valid()) {
41911b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          if (entry.end_pos() <= function_block_pos) {
41921b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org            // End position greater than end of stream is safe, and hard
41931b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org            // to check.
41941b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org            ReportInvalidPreparseData(function_name, CHECK_OK);
41951b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          }
41961b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          scanner().SeekForward(entry.end_pos() - 1);
41971b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
41981b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          scope->set_end_position(entry.end_pos());
41991b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          Expect(Token::RBRACE, CHECK_OK);
42001b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          isolate()->counters()->total_preparse_skipped()->Increment(
42011b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org              scope->end_position() - function_block_pos);
42021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          materialized_literal_count = entry.literal_count();
42031b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          expected_property_count = entry.property_count();
42041b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          top_scope_->SetLanguageMode(entry.language_mode());
42051b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        } else {
42061b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          is_lazily_compiled = false;
42071b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        }
4208d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org      } else {
42091b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        // With no preparser data, we partially parse the function, without
42101b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        // building an AST. This gathers the data needed to build a lazy
42111b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        // function.
42121b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        SingletonLogger logger;
4213a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
4214a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        if (result == PreParser::kPreParseStackOverflow) {
42151b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          // Propagate stack overflow.
4216a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          set_stack_overflow();
42171b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          *ok = false;
42181b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          return NULL;
4219d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org        }
42201b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        if (logger.has_error()) {
42211b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          const char* arg = logger.argument_opt();
42221b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          Vector<const char*> args;
42231b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          if (arg != NULL) {
42241b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org            args = Vector<const char*>(&arg, 1);
42251b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          }
42261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
42271b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                          logger.message(), args);
42281b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          *ok = false;
42291b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          return NULL;
42301b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        }
42311b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        scope->set_end_position(logger.end());
42321b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        Expect(Token::RBRACE, CHECK_OK);
4233d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org        isolate()->counters()->total_preparse_skipped()->Increment(
4234394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com            scope->end_position() - function_block_pos);
42351b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        materialized_literal_count = logger.literals();
42361b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        expected_property_count = logger.properties();
42371b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        top_scope_->SetLanguageMode(logger.language_mode());
42384a2e25edf994c4e3ff22fea6d432839192666139erik.corry@gmail.com      }
4239d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org    }
4240d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org
4241d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org    if (!is_lazily_compiled) {
4242471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
42437028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      body = new(zone()) ZoneList<Statement*>(8, zone());
424404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org      if (fvar != NULL) {
424528583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org        VariableProxy* fproxy = top_scope_->NewUnresolved(
424628583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org            factory(), function_name, Interface::NewConst());
424704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org        fproxy->BindTo(fvar);
4248b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        body->Add(factory()->NewExpressionStatement(
4249b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            factory()->NewAssignment(fvar_init_op,
4250b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                     fproxy,
4251a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                     factory()->NewThisFunction(pos),
4252a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                     RelocInfo::kNoPosition),
4253a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            RelocInfo::kNoPosition), zone());
425404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org      }
4255e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
4256e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // For generators, allocate and yield an iterator on function entry.
4257e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      if (is_generator) {
4258e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        ZoneList<Expression*>* arguments =
4259e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org            new(zone()) ZoneList<Expression*>(0, zone());
4260e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        CallRuntime* allocation = factory()->NewCallRuntime(
4261e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org            isolate()->factory()->empty_string(),
4262e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org            Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject),
4263a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            arguments, pos);
4264e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        VariableProxy* init_proxy = factory()->NewVariableProxy(
4265e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org            current_function_state_->generator_object_variable());
4266e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        Assignment* assignment = factory()->NewAssignment(
4267e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org            Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
4268e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        VariableProxy* get_proxy = factory()->NewVariableProxy(
4269e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org            current_function_state_->generator_object_variable());
4270e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        Yield* yield = factory()->NewYield(
427177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org            get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
4272a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        body->Add(factory()->NewExpressionStatement(
4273a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            yield, RelocInfo::kNoPosition), zone());
4274e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      }
4275e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
427633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
4277fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org
427877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      if (is_generator) {
427977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org        VariableProxy* get_proxy = factory()->NewVariableProxy(
428077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org            current_function_state_->generator_object_variable());
428177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org        Expression *undefined = factory()->NewLiteral(
4282a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
428377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org        Yield* yield = factory()->NewYield(
428477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org            get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
4285a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        body->Add(factory()->NewExpressionStatement(
4286a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            yield, RelocInfo::kNoPosition), zone());
428777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      }
428877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
4289c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      materialized_literal_count = function_state.materialized_literal_count();
4290c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      expected_property_count = function_state.expected_property_count();
429104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org      handler_count = function_state.handler_count();
429243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4293d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      Expect(Token::RBRACE, CHECK_OK);
4294394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      scope->set_end_position(scanner().location().end_pos);
429543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
429643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
42970a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Validate strict mode.
42981b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    if (!top_scope_->is_classic_mode()) {
42997c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org      if (IsEvalOrArguments(function_name)) {
4300394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        int start_pos = scope->start_position();
4301a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        int position = function_token_pos != RelocInfo::kNoPosition
4302a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
430383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        Scanner::Location location = Scanner::Location(position, start_pos);
430483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        ReportMessageAt(location,
43050a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org                        "strict_function_name", Vector<const char*>::empty());
43060a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        *ok = false;
43070a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        return NULL;
43080a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      }
4309378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      if (name_loc.IsValid()) {
4310378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        ReportMessageAt(name_loc, "strict_param_name",
4311378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org                        Vector<const char*>::empty());
4312378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        *ok = false;
4313378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        return NULL;
4314378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      }
4315378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      if (dupe_loc.IsValid()) {
4316378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        ReportMessageAt(dupe_loc, "strict_param_dupe",
4317378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org                        Vector<const char*>::empty());
4318378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        *ok = false;
4319378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        return NULL;
4320378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      }
432104921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      if (name_is_strict_reserved) {
4322394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        int start_pos = scope->start_position();
4323a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        int position = function_token_pos != RelocInfo::kNoPosition
4324a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
432583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        Scanner::Location location = Scanner::Location(position, start_pos);
432683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        ReportMessageAt(location, "strict_reserved_word",
432783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org                        Vector<const char*>::empty());
432883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        *ok = false;
432983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        return NULL;
433083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
433183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      if (reserved_loc.IsValid()) {
433283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        ReportMessageAt(reserved_loc, "strict_reserved_word",
433383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org                        Vector<const char*>::empty());
433483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        *ok = false;
433583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        return NULL;
433683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
4337394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      CheckOctalLiteral(scope->start_position(),
4338394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                        scope->end_position(),
4339394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                        CHECK_OK);
43400a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
4341b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    ast_properties = *factory()->visitor()->ast_properties();
43422c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
434344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
43440a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
43451b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (is_extended_mode()) {
43461805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    CheckConflictingVarDeclarations(scope, CHECK_OK);
43471805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  }
43481805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
434944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  FunctionLiteral* function_literal =
4350b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      factory()->NewFunctionLiteral(function_name,
4351b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                    scope,
4352b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                    body,
4353b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                    materialized_literal_count,
4354b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                    expected_property_count,
4355b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                    handler_count,
4356b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org                                    num_parameters,
435756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                                    duplicate_parameters,
4358dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                                    function_type,
4359471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                                    FunctionLiteral::kIsFunction,
4360f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                                    parenthesized,
4361a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                    generator,
4362a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org                                    pos);
4363a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  function_literal->set_function_token_position(function_token_pos);
4364b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  function_literal->set_ast_properties(&ast_properties);
43652c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org  function_literal->set_dont_optimize_reason(dont_optimize_reason);
43665d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org
43677c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
436844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  return function_literal;
436943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
437043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
437143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4372a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.orgPreParser::PreParseResult Parser::LazyParseFunctionLiteral(
43731b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    SingletonLogger* logger) {
43741b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
43751b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  ASSERT_EQ(Token::LBRACE, scanner().current_token());
43761b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
43771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (reusable_preparser_ == NULL) {
43781b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    intptr_t stack_limit = isolate()->stack_guard()->real_climit();
4379a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit);
4380e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
4381e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_modules(allow_modules());
4382e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
4383e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_lazy(true);
4384e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_generators(allow_generators());
43851fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    reusable_preparser_->set_allow_for_of(allow_for_of());
4386ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    reusable_preparser_->set_allow_harmony_numeric_literals(
4387ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org        allow_harmony_numeric_literals());
43881b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
4389a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  PreParser::PreParseResult result =
43901b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
4391f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                                                is_generator(),
43921b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                                                logger);
43931b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  return result;
43941b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org}
43951b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
43961b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
439743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseV8Intrinsic(bool* ok) {
439843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // CallRuntime ::
439943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '%' Identifier Arguments
440043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4401a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
440243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::MOD, CHECK_OK);
440343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Handle<String> name = ParseIdentifier(CHECK_OK);
440443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
4405d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
4406d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  if (extension_ != NULL) {
440743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // The extension structures are only accessible while parsing the
440843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // very first time not when reparsing because of lazy compilation.
44094f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    top_scope_->DeclarationScope()->ForceEagerCompilation();
441043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
441143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
44124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  const Runtime::Function* function = Runtime::FunctionForName(name);
441343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4414d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Check for built-in IS_VAR macro.
4415d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  if (function != NULL &&
4416d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->intrinsic_type == Runtime::RUNTIME &&
4417d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->function_id == Runtime::kIS_VAR) {
4418d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    // %IS_VAR(x) evaluates to x if x is a variable,
4419d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    // leads to a parse error otherwise.  Could be implemented as an
4420d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    // inline function %_IS_VAR(x) to eliminate this special case.
4421d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
4422d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      return args->at(0);
4423d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    } else {
4424f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      ReportMessage("not_isvar", Vector<const char*>::empty());
4425d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      *ok = false;
442643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return NULL;
442743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
442843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
442943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4430d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Check that the expected number of arguments are being passed.
4431d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  if (function != NULL &&
4432d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->nargs != -1 &&
4433d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->nargs != args->length()) {
4434d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    ReportMessage("illegal_access", Vector<const char*>::empty());
4435d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    *ok = false;
4436d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    return NULL;
4437de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  }
4438de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org
4439de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  // Check that the function is defined if it's an inline runtime call.
4440de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  if (function == NULL && name->Get(0) == '_') {
4441de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org    ReportMessage("not_defined", Vector<Handle<String> >(&name, 1));
4442de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org    *ok = false;
4443de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org    return NULL;
4444f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org  }
4445f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org
4446d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // We have a valid intrinsics call or a call to a builtin.
4447a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewCallRuntime(name, function, args, pos);
444843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
444943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
445043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4451a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.orgbool ParserBase::peek_any_identifier() {
445283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  Token::Value next = peek();
445383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  return next == Token::IDENTIFIER ||
445404921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org         next == Token::FUTURE_RESERVED_WORD ||
4455f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org         next == Token::FUTURE_STRICT_RESERVED_WORD ||
4456f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org         next == Token::YIELD;
445783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org}
445883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
445983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
4460b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgbool ParserBase::CheckContextualKeyword(Vector<const char> keyword) {
44611fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  if (peek() == Token::IDENTIFIER &&
4462b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org      scanner()->is_next_contextual_keyword(keyword)) {
44631fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Consume(Token::IDENTIFIER);
44641fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    return true;
44651fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  }
44661fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  return false;
44671fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org}
44681fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
44691fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
4470a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.orgvoid ParserBase::ExpectSemicolon(bool* ok) {
447143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Check for automatic semicolon insertion according to
447243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // the rules given in ECMA-262, section 7.9, page 21.
447343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value tok = peek();
447443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (tok == Token::SEMICOLON) {
447543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Next();
447643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return;
447743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
4478a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
447943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      tok == Token::RBRACE ||
448043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      tok == Token::EOS) {
448143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return;
448243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
448343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SEMICOLON, ok);
448443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
448543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
448643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4487b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgvoid ParserBase::ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
4488812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Expect(Token::IDENTIFIER, ok);
4489812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  if (!*ok) return;
4490b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  if (!scanner()->is_literal_contextual_keyword(keyword)) {
4491b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    ReportUnexpectedToken(scanner()->current_token());
4492812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    *ok = false;
4493812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
4494812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org}
4495812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
4496812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
4497a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.orgLiteral* Parser::GetLiteralUndefined(int position) {
4498a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewLiteral(
4499a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      isolate()->factory()->undefined_value(), position);
450043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
450143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
450243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4503a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.orgLiteral* Parser::GetLiteralTheHole(int position) {
4504a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewLiteral(
4505a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      isolate()->factory()->the_hole_value(), RelocInfo::kNoPosition);
450643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
450743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
450843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4509b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Parses an identifier that is valid for the current scope, in particular it
451004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org// fails on strict mode future reserved keywords in a strict scope.
451143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenHandle<String> Parser::ParseIdentifier(bool* ok) {
4512f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Token::Value next = Next();
4513f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  if (next == Token::IDENTIFIER ||
4514f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      (top_scope_->is_classic_mode() &&
4515f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org       (next == Token::FUTURE_STRICT_RESERVED_WORD ||
4516f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org        (next == Token::YIELD && !is_generator())))) {
4517bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    return GetSymbol();
4518f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else {
4519f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    ReportUnexpectedToken(next);
4520f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    *ok = false;
4521f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    return Handle<String>();
452204921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  }
452383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org}
452483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
452583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
452604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org// Parses and identifier or a strict mode future reserved word, and indicate
452704921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org// whether it is strict mode future reserved.
452804921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.orgHandle<String> Parser::ParseIdentifierOrStrictReservedWord(
452904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org    bool* is_strict_reserved, bool* ok) {
4530f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Token::Value next = Next();
4531f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  if (next == Token::IDENTIFIER) {
4532f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    *is_strict_reserved = false;
4533f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
4534f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org             (next == Token::YIELD && !is_generator())) {
453504921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org    *is_strict_reserved = true;
4536f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else {
4537f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    ReportUnexpectedToken(next);
4538f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    *ok = false;
4539f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    return Handle<String>();
454083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
4541bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  return GetSymbol();
454243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
454343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4544d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org
4545d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.orgHandle<String> Parser::ParseIdentifierName(bool* ok) {
4546d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org  Token::Value next = Next();
454783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  if (next != Token::IDENTIFIER &&
454804921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      next != Token::FUTURE_RESERVED_WORD &&
454904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      next != Token::FUTURE_STRICT_RESERVED_WORD &&
455004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      !Token::IsKeyword(next)) {
4551d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org    ReportUnexpectedToken(next);
4552d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org    *ok = false;
4553d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org    return Handle<String>();
4554d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org  }
4555bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  return GetSymbol();
4556d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org}
4557d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org
4558378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
455964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid Parser::MarkAsLValue(Expression* expression) {
456064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  VariableProxy* proxy = expression != NULL
456164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      ? expression->AsVariableProxy()
456264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      : NULL;
456364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
456464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (proxy != NULL) proxy->MarkAsLValue();
456564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org}
456664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
456764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
4568378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// Checks LHS expression for assignment and prefix/postfix increment/decrement
4569378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// in strict mode.
4570378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.orgvoid Parser::CheckStrictModeLValue(Expression* expression,
4571378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org                                   const char* error,
4572378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org                                   bool* ok) {
45731b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  ASSERT(!top_scope_->is_classic_mode());
4574378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  VariableProxy* lhs = expression != NULL
4575378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      ? expression->AsVariableProxy()
4576378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      : NULL;
4577378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
4578378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
4579378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    ReportMessage(error, Vector<const char*>::empty());
4580378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    *ok = false;
4581378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
4582378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
4583378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
4584378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
45851c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// Checks whether an octal literal was last seen between beg_pos and end_pos.
45861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// If so, reports an error. Only called for strict mode.
4587b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgvoid ParserBase::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
4588b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  Scanner::Location octal = scanner()->octal_position();
4589b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  if (octal.IsValid() && beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
4590b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    ReportMessageAt(octal, "strict_octal_literal");
4591b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    scanner()->clear_octal_position();
45920ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    *ok = false;
45930ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  }
45940ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org}
45950ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4596d3b3be0240773cedde121ab23064d32f2c50a74fsgjesse@chromium.org
45971805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgvoid Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
45981805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  Declaration* decl = scope->CheckConflictingVarDeclarations();
45991805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  if (decl != NULL) {
46001805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    // In harmony mode we treat conflicting variable bindinds as early
46011805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    // errors. See ES5 16 for a definition of early errors.
46021805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    Handle<String> name = decl->proxy()->name();
460383e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org    SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
46041805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    const char* elms[2] = { "Variable", *c_string };
46051805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    Vector<const char*> args(elms, 2);
46061805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    int position = decl->proxy()->position();
46071805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    Scanner::Location location = position == RelocInfo::kNoPosition
46081805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org        ? Scanner::Location::invalid()
46091805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org        : Scanner::Location(position, position + 1);
46101805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    ReportMessageAt(location, "redeclaration", args);
46111805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    *ok = false;
46121805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  }
46131805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org}
46141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
46151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
461604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org// This function reads an identifier name and determines whether or not it
461783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org// is 'get' or 'set'.
461804921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.orgHandle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
461904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org                                                     bool* is_set,
462004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org                                                     bool* ok) {
462104921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  Handle<String> result = ParseIdentifierName(ok);
462243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (!*ok) return Handle<String>();
46239e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
46249e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    const char* token = scanner().literal_ascii_string().start();
46259e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    *is_get = strncmp(token, "get", 3) == 0;
46269e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
462743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
462883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  return result;
462943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
463043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
463143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
463243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
463343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Parser support
463443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
463543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
463643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenbool Parser::TargetStackContainsLabel(Handle<String> label) {
4637b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4638b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    BreakableStatement* stat = t->node()->AsBreakableStatement();
463943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (stat != NULL && ContainsLabel(stat->labels(), label))
464043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return true;
464143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
464243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return false;
464343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
464443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
464543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
464643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenBreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
464743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool anonymous = label.is_null();
4648b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4649b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    BreakableStatement* stat = t->node()->AsBreakableStatement();
465043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (stat == NULL) continue;
465143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if ((anonymous && stat->is_target_for_anonymous()) ||
465243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        (!anonymous && ContainsLabel(stat->labels(), label))) {
4653b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org      RegisterTargetUse(stat->break_target(), t->previous());
465443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return stat;
465543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
465643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
465743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return NULL;
465843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
465943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
466043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
466143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenIterationStatement* Parser::LookupContinueTarget(Handle<String> label,
466243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                                 bool* ok) {
466343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool anonymous = label.is_null();
4664b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4665b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    IterationStatement* stat = t->node()->AsIterationStatement();
466643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (stat == NULL) continue;
466743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
466843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ASSERT(stat->is_target_for_anonymous());
466943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (anonymous || ContainsLabel(stat->labels(), label)) {
4670b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org      RegisterTargetUse(stat->continue_target(), t->previous());
467143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return stat;
467243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
467343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
467443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return NULL;
467543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
467643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
467743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
467844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgvoid Parser::RegisterTargetUse(Label* target, Target* stop) {
4679b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  // Register that a break target found at the given stop in the
46807be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  // target stack has been used from the top of the target stack. Add
46817be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  // the break target to any TargetCollectors passed on the stack.
4682b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != stop; t = t->previous()) {
4683b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    TargetCollector* collector = t->node()->AsTargetCollector();
46847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (collector != NULL) collector->AddTarget(target, zone());
468543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
468643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
468743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
468843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4689dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgExpression* Parser::NewThrowReferenceError(Handle<String> message) {
46904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  return NewThrowError(isolate()->factory()->MakeReferenceError_string(),
4691dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                       message, HandleVector<Object>(NULL, 0));
469243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
469343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
469443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4695dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgExpression* Parser::NewThrowSyntaxError(Handle<String> message,
469643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                        Handle<Object> first) {
469743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int argc = first.is_null() ? 0 : 1;
469843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
4699ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  return NewThrowError(
4700dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      isolate()->factory()->MakeSyntaxError_string(), message, arguments);
470143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
470243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
470343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4704dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgExpression* Parser::NewThrowTypeError(Handle<String> message,
470543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                      Handle<Object> first,
470643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                      Handle<Object> second) {
470743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(!first.is_null() && !second.is_null());
470843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Handle<Object> elements[] = { first, second };
470943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Vector< Handle<Object> > arguments =
471043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      HandleVector<Object>(elements, ARRAY_SIZE(elements));
4711ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  return NewThrowError(
4712dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      isolate()->factory()->MakeTypeError_string(), message, arguments);
471343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
471443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
471543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
471643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::NewThrowError(Handle<String> constructor,
4717dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org                                  Handle<String> message,
471843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                  Vector< Handle<Object> > arguments) {
471943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int argc = arguments.length();
4720ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
4721ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                                                    TENURED);
472243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (int i = 0; i < argc; i++) {
472343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Handle<Object> element = arguments[i];
472443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (!element.is_null()) {
4725496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      elements->set(i, *element);
472643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
472743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
4728fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(
4729fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org      elements, FAST_ELEMENTS, TENURED);
4730496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
4731a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
47327028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2, zone());
4733a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  args->Add(factory()->NewLiteral(message, pos), zone());
4734a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  args->Add(factory()->NewLiteral(array, pos), zone());
4735b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  CallRuntime* call_constructor =
4736a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewCallRuntime(constructor, NULL, args, pos);
4737a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewThrow(call_constructor, pos);
473843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
473943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4740e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
4741b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// ----------------------------------------------------------------------------
4742a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Regular expressions
4743a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4744a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4745a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpParser::RegExpParser(FlatStringReader* in,
4746a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                           Handle<String>* error,
47475a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                           bool multiline,
47485a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                           Zone* zone)
47493d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org    : isolate_(zone->isolate()),
47505a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      zone_(zone),
4751ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      error_(error),
4752ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      captures_(NULL),
4753ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      in_(in),
4754ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      current_(kEndMarker),
4755ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      next_pos_(0),
4756ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      capture_count_(0),
4757ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      has_more_(true),
4758ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      multiline_(multiline),
4759ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      simple_(false),
4760ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      contains_anchor_(false),
4761ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      is_scanned_for_captures_(false),
4762ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      failed_(false) {
4763023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  Advance();
4764a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4765a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4766a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4767a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orguc32 RegExpParser::Next() {
4768a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (has_next()) {
4769a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return in()->Get(next_pos_);
4770a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
4771a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return kEndMarker;
4772a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4773a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4774a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4775a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4776a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::Advance() {
4777a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (next_pos_ < in()->length()) {
4778ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    StackLimitCheck check(isolate());
4779a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (check.HasOverflowed()) {
4780ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ReportError(CStrVector(Isolate::kStackOverflowMessage));
47815a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    } else if (zone()->excess_allocation()) {
4782a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      ReportError(CStrVector("Regular expression too large"));
4783a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
4784a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      current_ = in()->Get(next_pos_);
4785a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      next_pos_++;
4786a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4787a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
4788a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    current_ = kEndMarker;
4789a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    has_more_ = false;
4790a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4791a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4792a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4793a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4794a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::Reset(int pos) {
4795a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  next_pos_ = pos;
479653ad17558c81e6099cef4442237d7da643a5becfsvenpanne@chromium.org  has_more_ = (pos < in()->length());
4797a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
4798a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4799a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4800a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4801a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::Advance(int dist) {
4802023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  next_pos_ += dist - 1;
4803023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  Advance();
4804a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4805a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4806a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
480737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.combool RegExpParser::simple() {
480837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  return simple_;
4809a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4810a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4811e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
4812a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4813a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  failed_ = true;
4814ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
4815a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Zip to the end to make sure the no more input is read.
4816a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  current_ = kEndMarker;
4817a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  next_pos_ = in()->length();
4818a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return NULL;
4819a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4820a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4821a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4822a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Pattern ::
4823a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Disjunction
4824a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ParsePattern() {
4825a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  RegExpTree* result = ParseDisjunction(CHECK_FAILED);
482686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  ASSERT(!has_more());
48277ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  // If the result of parsing is a literal string atom, and it has the
48287ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  // same length as the input, then the atom is identical to the input.
48297ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
48307ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org    simple_ = true;
48317ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  }
4832a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return result;
4833a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4834a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4835a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4836a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Disjunction ::
4837a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Alternative
4838a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Alternative | Disjunction
4839a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Alternative ::
4840a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   [empty]
4841a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Term Alternative
4842a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Term ::
4843a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Assertion
4844a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Atom
4845a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Atom Quantifier
4846a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ParseDisjunction() {
484786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Used to store current state while parsing subexpressions.
4848400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org  RegExpParserState initial_state(NULL, INITIAL, 0, zone());
484986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  RegExpParserState* stored_state = &initial_state;
485086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Cache the builder in a local variable for quick access.
485186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  RegExpBuilder* builder = initial_state.builder();
4852a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (true) {
4853a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (current()) {
4854a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case kEndMarker:
485586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      if (stored_state->IsSubexpression()) {
485686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        // Inside a parenthesized group when hitting end of input.
485786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        ReportError(CStrVector("Unterminated group") CHECK_FAILED);
485886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      }
485986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      ASSERT_EQ(INITIAL, stored_state->group_type());
486086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Parsing completed successfully.
486186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      return builder->ToRegExp();
486286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    case ')': {
486386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      if (!stored_state->IsSubexpression()) {
486486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
486586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      }
486686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      ASSERT_NE(INITIAL, stored_state->group_type());
486786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
4868a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
486986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // End disjunction parsing and convert builder content to new single
487086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // regexp atom.
487186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      RegExpTree* body = builder->ToRegExp();
487286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
487386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      int end_capture_index = captures_started();
487486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
487586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      int capture_index = stored_state->capture_index();
4876dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      SubexpressionType group_type = stored_state->group_type();
487786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
487886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Restore previous state.
487986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      stored_state = stored_state->previous_state();
488086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder = stored_state->builder();
488186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
488286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Build result of subexpression.
4883dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      if (group_type == CAPTURE) {
4884c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org        RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
488586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        captures_->at(capture_index - 1) = capture;
488686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        body = capture;
4887dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      } else if (group_type != GROUPING) {
4888dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org        ASSERT(group_type == POSITIVE_LOOKAHEAD ||
4889dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org               group_type == NEGATIVE_LOOKAHEAD);
4890dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org        bool is_positive = (group_type == POSITIVE_LOOKAHEAD);
4891c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org        body = new(zone()) RegExpLookahead(body,
489286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org                                   is_positive,
489386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org                                   end_capture_index - capture_index,
489486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org                                   capture_index);
4895a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
489686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddAtom(body);
489749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // For compatability with JSC and ES3, we allow quantifiers after
489849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // lookaheads, and break in all cases.
489986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      break;
490086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    }
490186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    case '|': {
490286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      Advance();
490386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->NewAlternative();
4904a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
4905a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4906a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '*':
4907a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '+':
4908a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '?':
4909e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return ReportError(CStrVector("Nothing to repeat"));
4910a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '^': {
4911a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4912245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      if (multiline_) {
491386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4914c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
4915245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      } else {
491686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4917c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
4918245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        set_contains_anchor();
4919245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      }
4920a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
4921a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4922a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '$': {
4923a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4924dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      RegExpAssertion::AssertionType assertion_type =
4925a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          multiline_ ? RegExpAssertion::END_OF_LINE :
4926a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                       RegExpAssertion::END_OF_INPUT;
4927dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      builder->AddAssertion(new(zone()) RegExpAssertion(assertion_type));
4928a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
4929a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4930a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '.': {
4931a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4932a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // everything except \x0a, \x0d, \u2028 and \u2029
493340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      ZoneList<CharacterRange>* ranges =
49347028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          new(zone()) ZoneList<CharacterRange>(2, zone());
49357028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      CharacterRange::AddClassEscape('.', ranges, zone());
4936c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
493786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddAtom(atom);
4938a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4939a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4940a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '(': {
4941dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      SubexpressionType subexpr_type = CAPTURE;
494286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      Advance();
494386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      if (current() == '?') {
494486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        switch (Next()) {
494586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          case ':':
4946dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org            subexpr_type = GROUPING;
494786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
494886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          case '=':
4949dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org            subexpr_type = POSITIVE_LOOKAHEAD;
495086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
495186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          case '!':
4952dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org            subexpr_type = NEGATIVE_LOOKAHEAD;
495386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
495486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          default:
495586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            ReportError(CStrVector("Invalid group") CHECK_FAILED);
495686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
495786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        }
495886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        Advance(2);
495986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      } else {
496086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        if (captures_ == NULL) {
49617028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          captures_ = new(zone()) ZoneList<RegExpCapture*>(2, zone());
496286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        }
496386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        if (captures_started() >= kMaxCaptures) {
496486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          ReportError(CStrVector("Too many captures") CHECK_FAILED);
496586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        }
49667028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        captures_->Add(NULL, zone());
496786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      }
496886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Store current state and begin new disjunction parsing.
4969dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      stored_state = new(zone()) RegExpParserState(stored_state, subexpr_type,
4970400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org                                                   captures_started(), zone());
497186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder = stored_state->builder();
497249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      continue;
4973a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4974a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '[': {
4975a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
497686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddAtom(atom);
4977a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4978a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4979a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Atom ::
4980a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   \ AtomEscape
4981a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '\\':
4982a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      switch (Next()) {
4983a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case kEndMarker:
4984e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        return ReportError(CStrVector("\\ at end of pattern"));
4985a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'b':
4986a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
498786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4988c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
4989a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        continue;
4990a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'B':
4991a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
499286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4993c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
4994a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        continue;
499549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // AtomEscape ::
499649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      //   CharacterClassEscape
499749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      //
499849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // CharacterClassEscape :: one of
499949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      //   d D s S w W
5000a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
5001a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 c = Next();
5002a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
500340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org        ZoneList<CharacterRange>* ranges =
50047028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org            new(zone()) ZoneList<CharacterRange>(2, zone());
50057028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        CharacterRange::AddClassEscape(c, ranges, zone());
5006c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org        RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
500786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAtom(atom);
500886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        break;
5009a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5010a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '1': case '2': case '3': case '4': case '5': case '6':
5011a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '7': case '8': case '9': {
5012a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        int index = 0;
5013a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (ParseBackReferenceIndex(&index)) {
501486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          RegExpCapture* capture = NULL;
501586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          if (captures_ != NULL && index <= captures_->length()) {
501686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            capture = captures_->at(index - 1);
501786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          }
501886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          if (capture == NULL) {
501986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            builder->AddEmpty();
502086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
5021a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          }
5022c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org          RegExpTree* atom = new(zone()) RegExpBackReference(capture);
502386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddAtom(atom);
502486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          break;
5025a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
5026a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 first_digit = Next();
5027a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (first_digit == '8' || first_digit == '9') {
5028a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          // Treat as identity escape
502986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter(first_digit);
5030a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          Advance(2);
5031a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          break;
5032a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
5033a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5034a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // FALLTHROUGH
5035a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '0': {
5036a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance();
5037a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 octal = ParseOctalLiteral();
503886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter(octal);
5039a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5040a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5041a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // ControlEscape :: one of
5042a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      //   f n r t v
5043a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'f':
5044a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
504586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\f');
5046a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5047a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'n':
5048a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
504986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\n');
5050a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5051a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'r':
5052a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
505386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\r');
5054a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5055a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 't':
5056a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
505786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\t');
5058a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5059a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'v':
5060a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
506186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\v');
5062a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5063a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'c': {
5064d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        Advance();
5065d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        uc32 controlLetter = Next();
5066d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // Special case if it is an ASCII letter.
5067d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // Convert lower case letters to uppercase.
5068d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        uc32 letter = controlLetter & ~('a' ^ 'A');
5069d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        if (letter < 'A' || 'Z' < letter) {
5070d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
5071d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // This is outside the specification. We match JSC in
5072d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // reading the backslash as a literal character instead
5073d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // of as starting an escape.
5074d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          builder->AddCharacter('\\');
5075d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        } else {
5076d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          Advance(2);
5077d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          builder->AddCharacter(controlLetter & 0x1f);
5078d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        }
5079a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5080a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5081a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'x': {
5082a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
5083a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 value;
5084a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (ParseHexEscape(2, &value)) {
508586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter(value);
5086a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        } else {
508786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter('x');
5088a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
5089a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5090a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5091a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'u': {
5092a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
5093a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 value;
5094a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (ParseHexEscape(4, &value)) {
509586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter(value);
5096a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        } else {
509786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter('u');
5098a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
5099a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5100a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5101a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      default:
5102a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // Identity escape.
510386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter(Next());
5104a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
5105a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5106a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5107a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
5108a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '{': {
5109a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      int dummy;
5110a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseIntervalQuantifier(&dummy, &dummy)) {
5111a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
5112a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5113a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // fallthrough
5114a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5115a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default:
511686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddCharacter(current());
5117a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5118a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
5119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }  // end switch(current())
5120a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5121a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int min;
5122a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int max;
5123a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (current()) {
5124a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // QuantifierPrefix ::
5125a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   *
5126a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   +
5127a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   ?
5128a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   {
5129a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '*':
5130a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      min = 0;
513137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      max = RegExpTree::kInfinity;
5132a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5133a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
5134a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '+':
5135a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      min = 1;
513637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      max = RegExpTree::kInfinity;
5137a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
5139a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '?':
5140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      min = 0;
5141a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      max = 1;
5142a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5143a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
5144a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '{':
5145a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseIntervalQuantifier(&min, &max)) {
5146245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        if (max < min) {
5147245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          ReportError(CStrVector("numbers out of order in {} quantifier.")
5148245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                      CHECK_FAILED);
5149245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        }
5150a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5151a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      } else {
5152a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        continue;
5153a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5154a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default:
5155a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
5156a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5157dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY;
5158a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (current() == '?') {
5159dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      quantifier_type = RegExpQuantifier::NON_GREEDY;
51600c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      Advance();
51610c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
51620c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      // FLAG_regexp_possessive_quantifier is a debug-only flag.
5163dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      quantifier_type = RegExpQuantifier::POSSESSIVE;
5164a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5165a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5166dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    builder->AddQuantifierToAtom(min, max, quantifier_type);
5167a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5168a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5169a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5170a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5171a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#ifdef DEBUG
5172a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Currently only used in an ASSERT.
5173a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic bool IsSpecialClassEscape(uc32 c) {
5174a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  switch (c) {
5175a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'd': case 'D':
5176a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 's': case 'S':
5177a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'w': case 'W':
5178a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return true;
5179a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default:
5180a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
5181a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5182a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5183a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif
5184a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5185a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5186a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// In order to know whether an escape is a backreference or not we have to scan
5187a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// the entire regexp and find the number of capturing parentheses.  However we
5188a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// don't want to scan the regexp twice unless it is necessary.  This mini-parser
5189a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// is called when needed.  It can see the difference between capturing and
5190a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// noncapturing parentheses and can skip character classes and backslash-escaped
5191a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// characters.
5192a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::ScanForCaptures() {
5193a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Start with captures started previous to current position
5194a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int capture_count = captures_started();
5195a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Add count of captures after this position.
5196a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int n;
5197a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while ((n = current()) != kEndMarker) {
5198a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5199a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (n) {
5200a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '\\':
5201a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance();
5202a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5203a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '[': {
5204a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        int c;
5205a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        while ((c = current()) != kEndMarker) {
5206a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          Advance();
5207a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          if (c == '\\') {
5208a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            Advance();
5209a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          } else {
5210a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            if (c == ']') break;
5211a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          }
5212a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
5213a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5214a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5215a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '(':
5216a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (current() != '?') capture_count++;
5217a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5218a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5219a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5220a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  capture_count_ = capture_count;
5221a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  is_scanned_for_captures_ = true;
5222a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5223a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5224a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5225a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool RegExpParser::ParseBackReferenceIndex(int* index_out) {
5226a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT_EQ('\\', current());
5227a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT('1' <= Next() && Next() <= '9');
5228245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  // Try to parse a decimal literal that is no greater than the total number
5229245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  // of left capturing parentheses in the input.
5230a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int start = position();
5231a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int value = Next() - '0';
5232a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance(2);
5233a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (true) {
5234a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    uc32 c = current();
5235a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (IsDecimalDigit(c)) {
5236a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      value = 10 * value + (c - '0');
5237245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      if (value > kMaxCaptures) {
5238245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        Reset(start);
5239245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        return false;
5240245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      }
5241a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5242a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
5243a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
5244a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5245a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5246a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (value > captures_started()) {
5247a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!is_scanned_for_captures_) {
5248a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      int saved_position = position();
5249a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      ScanForCaptures();
5250a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Reset(saved_position);
5251a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5252a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (value > capture_count_) {
5253a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Reset(start);
5254a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
5255a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5256a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5257a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *index_out = value;
5258a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
5259a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5260a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5261a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5262a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// QuantifierPrefix ::
5263a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   { DecimalDigits }
5264a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   { DecimalDigits , }
5265a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   { DecimalDigits , DecimalDigits }
5266245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org//
5267245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org// Returns true if parsing succeeds, and set the min_out and max_out
5268245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org// values. Values are truncated to RegExpTree::kInfinity if they overflow.
5269a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
5270a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT_EQ(current(), '{');
5271a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int start = position();
5272a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
5273a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int min = 0;
5274a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!IsDecimalDigit(current())) {
5275a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Reset(start);
5276a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
5277a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5278a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (IsDecimalDigit(current())) {
5279245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    int next = current() - '0';
5280245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    if (min > (RegExpTree::kInfinity - next) / 10) {
5281245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      // Overflow. Skip past remaining decimal digits and return -1.
5282245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      do {
5283245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        Advance();
5284245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      } while (IsDecimalDigit(current()));
5285245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      min = RegExpTree::kInfinity;
5286245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      break;
5287245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    }
5288245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    min = 10 * min + next;
5289a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5290a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5291a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int max = 0;
5292a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (current() == '}') {
5293a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    max = min;
5294a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5295a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (current() == ',') {
5296a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5297a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (current() == '}') {
529837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      max = RegExpTree::kInfinity;
5299a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5300a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
5301a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      while (IsDecimalDigit(current())) {
5302245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        int next = current() - '0';
5303245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        if (max > (RegExpTree::kInfinity - next) / 10) {
5304245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          do {
5305245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org            Advance();
5306245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          } while (IsDecimalDigit(current()));
5307245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          max = RegExpTree::kInfinity;
5308245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          break;
5309245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        }
5310245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        max = 10 * max + next;
5311a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance();
5312a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5313a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (current() != '}') {
5314a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Reset(start);
5315a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return false;
5316a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5317a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5318a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5319a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
5320a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Reset(start);
5321a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
5322a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5323a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *min_out = min;
5324a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *max_out = max;
5325a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
5326a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5327a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5328a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5329a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orguc32 RegExpParser::ParseOctalLiteral() {
5330a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT('0' <= current() && current() <= '7');
5331a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // For compatibility with some other browsers (not all), we parse
5332a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // up to three octal digits with a value below 256.
5333a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  uc32 value = current() - '0';
5334a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
5335a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if ('0' <= current() && current() <= '7') {
5336a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    value = value * 8 + current() - '0';
5337a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5338a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (value < 32 && '0' <= current() && current() <= '7') {
5339a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      value = value * 8 + current() - '0';
5340a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5341a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5342a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5343a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return value;
5344a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5345a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5346a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5347a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool RegExpParser::ParseHexEscape(int length, uc32 *value) {
5348a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int start = position();
5349a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  uc32 val = 0;
5350a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  bool done = false;
5351a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  for (int i = 0; !done; i++) {
5352a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    uc32 c = current();
5353a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int d = HexValue(c);
5354a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (d < 0) {
5355a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Reset(start);
5356a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
5357a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5358a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    val = val * 16 + d;
5359a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5360a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (i == length - 1) {
5361a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      done = true;
5362a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5363a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5364a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *value = val;
5365a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
5366a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5367a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5368a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5369a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orguc32 RegExpParser::ParseClassCharacterEscape() {
5370a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(current() == '\\');
5371a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(has_next() && !IsSpecialClassEscape(Next()));
5372a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
5373a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  switch (current()) {
5374a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'b':
5375a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5376a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\b';
5377a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // ControlEscape :: one of
5378a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   f n r t v
5379a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'f':
5380a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5381a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\f';
5382a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'n':
5383a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5384a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\n';
5385a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'r':
5386a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5387a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\r';
5388a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 't':
5389a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5390a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\t';
5391a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'v':
5392a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5393a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\v';
5394d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    case 'c': {
5395d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      uc32 controlLetter = Next();
5396d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      uc32 letter = controlLetter & ~('A' ^ 'a');
5397d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // For compatibility with JSC, inside a character class
5398d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // we also accept digits and underscore as control characters.
5399d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      if ((controlLetter >= '0' && controlLetter <= '9') ||
5400d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          controlLetter == '_' ||
5401d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          (letter >= 'A' && letter <= 'Z')) {
5402d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        Advance(2);
5403d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // Control letters mapped to ASCII control characters in the range
5404d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // 0x00-0x1f.
5405d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        return controlLetter & 0x1f;
5406d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      }
5407d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // We match JSC in reading the backslash as a literal
5408d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // character instead of as starting an escape.
5409d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      return '\\';
5410d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
5411a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '0': case '1': case '2': case '3': case '4': case '5':
5412a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '6': case '7':
5413a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // For compatibility, we interpret a decimal escape that isn't
5414a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // a back reference (and therefore either \0 or not valid according
5415a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // to the specification) as a 1..3 digit octal character code.
5416a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return ParseOctalLiteral();
5417a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'x': {
5418a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5419a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      uc32 value;
5420a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseHexEscape(2, &value)) {
5421a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return value;
5422a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5423a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // If \x is not followed by a two-digit hexadecimal, treat it
5424a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // as an identity escape.
5425a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return 'x';
5426a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5427a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'u': {
5428a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5429a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      uc32 value;
5430a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseHexEscape(4, &value)) {
5431a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return value;
5432a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5433a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // If \u is not followed by a four-digit hexadecimal, treat it
5434a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // as an identity escape.
5435a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return 'u';
5436a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5437a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default: {
5438a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // Extended identity escape. We accept any character that hasn't
5439a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // been matched by a more specific case, not just the subset required
5440a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // by the ECMAScript specification.
5441a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      uc32 result = current();
5442a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5443a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return result;
5444a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5445a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5446a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return 0;
5447a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5448a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5449a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5450a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgCharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
5451a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT_EQ(0, *char_class);
5452a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  uc32 first = current();
5453a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (first == '\\') {
5454a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (Next()) {
5455a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
5456a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        *char_class = Next();
5457a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
5458a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return CharacterRange::Singleton(0);  // Return dummy value.
5459a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
546037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      case kEndMarker:
5461e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        return ReportError(CStrVector("\\ at end of pattern"));
5462a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      default:
5463a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
5464a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return CharacterRange::Singleton(c);
5465a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5466a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
5467a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5468a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return CharacterRange::Singleton(first);
5469a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5470a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5471a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5472a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
547314a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.orgstatic const uc16 kNoCharClass = 0;
547414a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org
547514a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org// Adds range or pre-defined character class to character ranges.
547614a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org// If char_class is not kInvalidClass, it's interpreted as a class
547714a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org// escape (i.e., 's' means whitespace, from '\s').
547814a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.orgstatic inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
547914a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org                                    uc16 char_class,
54807028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                    CharacterRange range,
54817028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                    Zone* zone) {
548214a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org  if (char_class != kNoCharClass) {
54837028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    CharacterRange::AddClassEscape(char_class, ranges, zone);
548414a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org  } else {
54857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    ranges->Add(range, zone);
548614a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org  }
548714a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org}
548814a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org
548914a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org
5490a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ParseCharacterClass() {
5491a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  static const char* kUnterminated = "Unterminated character class";
5492a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  static const char* kRangeOutOfOrder = "Range out of order in character class";
5493a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5494a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT_EQ(current(), '[');
5495a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
5496a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  bool is_negated = false;
5497a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (current() == '^') {
5498a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    is_negated = true;
5499a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
5500a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
55017028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<CharacterRange>* ranges =
55027028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      new(zone()) ZoneList<CharacterRange>(2, zone());
5503a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (has_more() && current() != ']') {
550414a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org    uc16 char_class = kNoCharClass;
5505a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
5506a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (current() == '-') {
5507a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
5508a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (current() == kEndMarker) {
5509a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // If we reach the end we break out of the loop and let the
5510a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // following code report an error.
5511a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5512a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      } else if (current() == ']') {
55137028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        AddRangeOrEscape(ranges, char_class, first, zone());
55147028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        ranges->Add(CharacterRange::Singleton('-'), zone());
5515a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
5516a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
551714a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org      uc16 char_class_2 = kNoCharClass;
551814a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org      CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
551914a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org      if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
552014a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org        // Either end is an escaped character class. Treat the '-' verbatim.
55217028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        AddRangeOrEscape(ranges, char_class, first, zone());
55227028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        ranges->Add(CharacterRange::Singleton('-'), zone());
55237028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        AddRangeOrEscape(ranges, char_class_2, next, zone());
552414a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org        continue;
5525a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
5526a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (first.from() > next.to()) {
5527a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
5528a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
55297028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ranges->Add(CharacterRange::Range(first.from(), next.to()), zone());
5530a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
55317028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      AddRangeOrEscape(ranges, char_class, first, zone());
5532a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
5533a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5534a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!has_more()) {
5535a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
5536a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5537a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
5538a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (ranges->length() == 0) {
55397028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    ranges->Add(CharacterRange::Everything(), zone());
5540a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    is_negated = !is_negated;
5541a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5542c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  return new(zone()) RegExpCharacterClass(ranges, is_negated);
5543a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5544a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5545a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5546a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// ----------------------------------------------------------------------------
554743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The Parser interface.
554843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
554943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenScriptDataImpl::~ScriptDataImpl() {
55505b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (owns_store_) store_.Dispose();
555143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
555243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
555343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
555443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint ScriptDataImpl::Length() {
55559155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  return store_.length() * sizeof(unsigned);
555643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
555743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
555843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
55599155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.orgconst char* ScriptDataImpl::Data() {
55609155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  return reinterpret_cast<const char*>(store_.start());
556143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
556243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
556343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
55640c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgbool ScriptDataImpl::HasError() {
55650c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  return has_error();
55660c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
55670c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
55680c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
5569d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.comvoid ScriptDataImpl::Initialize() {
5570c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // Prepares state for use.
5571beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5572beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    function_index_ = PreparseDataConstants::kHeaderSize;
5573beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    int symbol_data_offset = PreparseDataConstants::kHeaderSize
5574beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org        + store_[PreparseDataConstants::kFunctionsSizeOffset];
5575d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    if (store_.length() > symbol_data_offset) {
5576d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5577d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    } else {
5578d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      // Partial preparse causes no symbol information.
5579d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5580d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    }
5581d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5582d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  }
5583d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com}
5584d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
5585d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
5586d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.comint ScriptDataImpl::ReadNumber(byte** source) {
5587d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Reads a number from symbol_data_ in base 128. The most significant
5588d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // bit marks that there are more digits.
5589d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // If the first byte is 0x80 (kNumberTerminator), it would normally
5590d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // represent a leading zero. Since that is useless, and therefore won't
5591d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // appear as the first digit of any actual value, it is used to
5592d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // mark the end of the input stream.
5593d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  byte* data = *source;
5594d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  if (data >= symbol_data_end_) return -1;
5595d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  byte input = *data;
5596beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  if (input == PreparseDataConstants::kNumberTerminator) {
5597d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    // End of stream marker.
5598d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    return -1;
5599d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  }
5600d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  int result = input & 0x7f;
5601d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  data++;
5602d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  while ((input & 0x80u) != 0) {
5603d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    if (data >= symbol_data_end_) return -1;
5604d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    input = *data;
5605d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    result = (result << 7) | (input & 0x7f);
5606d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    data++;
5607d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  }
5608d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  *source = data;
5609d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  return result;
5610d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com}
5611d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
5612d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
561321b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org// Create a Scanner for the preparser to use as input, and preparse the source.
56143d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.orgScriptDataImpl* PreParserApi::PreParse(Isolate* isolate,
56153d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org                                       Utf16CharacterStream* source) {
5616e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CompleteParserRecorder recorder;
56171b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  HistogramTimerScope timer(isolate->counters()->pre_parse());
5618c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Scanner scanner(isolate->unicode_cache());
5619ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  intptr_t stack_limit = isolate->stack_guard()->real_climit();
5620a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  PreParser preparser(&scanner, &recorder, stack_limit);
5621e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  preparser.set_allow_lazy(true);
5622e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  preparser.set_allow_generators(FLAG_harmony_generators);
56231fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  preparser.set_allow_for_of(FLAG_harmony_iteration);
5624e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  preparser.set_allow_harmony_scoping(FLAG_harmony_scoping);
5625ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
5626e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  scanner.Initialize(source);
5627a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  PreParser::PreParseResult result = preparser.PreParseProgram();
5628a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  if (result == PreParser::kPreParseStackOverflow) {
5629ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->StackOverflow();
56304a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    return NULL;
56314a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  }
56324a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
56334a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Extract the accumulated data from the recorder as a single
56344a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // contiguous vector that we are responsible for disposing.
5635e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Vector<unsigned> store = recorder.ExtractData();
56364a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  return new ScriptDataImpl(store);
56374a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}
56384a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
56394a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
5640e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.orgbool RegExpParser::ParseRegExp(FlatStringReader* input,
5641e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org                               bool multiline,
56425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                               RegExpCompileData* result,
56435a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                               Zone* zone) {
5644a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(result != NULL);
56455a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  RegExpParser parser(input, &result->error, multiline, zone);
564637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  RegExpTree* tree = parser.ParsePattern();
5647a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (parser.failed()) {
564837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    ASSERT(tree == NULL);
5649a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ASSERT(!result->error.is_null());
5650a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
565137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    ASSERT(tree != NULL);
5652a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ASSERT(result->error.is_null());
565337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result->tree = tree;
565437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    int capture_count = parser.captures_started();
565537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5656245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    result->contains_anchor = parser.contains_anchor();
565737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result->capture_count = capture_count;
5658a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
5659a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return !parser.failed();
5660a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
5661a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5662a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
5663e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool Parser::Parse() {
5664e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(info()->function() == NULL);
5665b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org  FunctionLiteral* result = NULL;
5666e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (info()->is_lazy()) {
5667e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(!info()->is_eval());
5668e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (info()->shared_info()->is_function()) {
5669e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      result = ParseLazy();
567056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    } else {
5671e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      result = ParseProgram();
567256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
5673b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
5674e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ScriptDataImpl* pre_parse_data = info()->pre_parse_data();
5675e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    set_pre_parse_data(pre_parse_data);
5676e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (pre_parse_data != NULL && pre_parse_data->has_error()) {
5677e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      Scanner::Location loc = pre_parse_data->MessageLocation();
5678e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      const char* message = pre_parse_data->BuildMessage();
5679e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      Vector<const char*> args = pre_parse_data->BuildArgs();
5680e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      ReportMessageAt(loc, message, args);
5681b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org      DeleteArray(message);
5682b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org      for (int i = 0; i < args.length(); i++) {
5683b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org        DeleteArray(args[i]);
5684b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org      }
5685b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org      DeleteArray(args.start());
5686e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      ASSERT(info()->isolate()->has_pending_exception());
5687b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org    } else {
5688e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      result = ParseProgram();
5689b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org    }
5690b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
5691e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  info()->SetFunction(result);
5692b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org  return (result != NULL);
569343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
569443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
569543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} }  // namespace v8::internal
5696