blob: 04d510f2fdcf174fe9615e7e871fc20ae236ff2d [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "ast.h"
32#include "bootstrapper.h"
Steve Block6ded16b2010-05-10 14:33:55 +010033#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010035#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010036#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010037#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080039#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "runtime.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010041#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "string-stream.h"
43
Kristian Monsen25f61362010-05-21 11:50:48 +010044#include "ast-inl.h"
45#include "jump-target-inl.h"
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047namespace v8 {
48namespace internal {
49
Steve Blocka7e24c12009-10-30 11:49:00 +000050// PositionStack is used for on-stack allocation of token positions for
51// new expressions. Please look at ParseNewExpression.
52
53class PositionStack {
54 public:
55 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
56 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
57
58 class Element {
59 public:
60 Element(PositionStack* stack, int value) {
61 previous_ = stack->top();
62 value_ = value;
63 stack->set_top(this);
64 }
65
66 private:
67 Element* previous() { return previous_; }
68 int value() { return value_; }
69 friend class PositionStack;
70 Element* previous_;
71 int value_;
72 };
73
74 bool is_empty() { return top_ == NULL; }
75 int pop() {
76 ASSERT(!is_empty());
77 int result = top_->value();
78 top_ = top_->previous();
79 return result;
80 }
81
82 private:
83 Element* top() { return top_; }
84 void set_top(Element* value) { top_ = value; }
85 Element* top_;
86 bool* ok_;
87};
88
89
Steve Blocka7e24c12009-10-30 11:49:00 +000090RegExpBuilder::RegExpBuilder()
91 : pending_empty_(false),
92 characters_(NULL),
93 terms_(),
94 alternatives_()
95#ifdef DEBUG
96 , last_added_(ADD_NONE)
97#endif
98 {}
99
100
101void RegExpBuilder::FlushCharacters() {
102 pending_empty_ = false;
103 if (characters_ != NULL) {
104 RegExpTree* atom = new RegExpAtom(characters_->ToConstVector());
105 characters_ = NULL;
106 text_.Add(atom);
107 LAST(ADD_ATOM);
108 }
109}
110
111
112void RegExpBuilder::FlushText() {
113 FlushCharacters();
114 int num_text = text_.length();
115 if (num_text == 0) {
116 return;
117 } else if (num_text == 1) {
118 terms_.Add(text_.last());
119 } else {
120 RegExpText* text = new RegExpText();
121 for (int i = 0; i < num_text; i++)
122 text_.Get(i)->AppendToText(text);
123 terms_.Add(text);
124 }
125 text_.Clear();
126}
127
128
129void RegExpBuilder::AddCharacter(uc16 c) {
130 pending_empty_ = false;
131 if (characters_ == NULL) {
132 characters_ = new ZoneList<uc16>(4);
133 }
134 characters_->Add(c);
135 LAST(ADD_CHAR);
136}
137
138
139void RegExpBuilder::AddEmpty() {
140 pending_empty_ = true;
141}
142
143
144void RegExpBuilder::AddAtom(RegExpTree* term) {
145 if (term->IsEmpty()) {
146 AddEmpty();
147 return;
148 }
149 if (term->IsTextElement()) {
150 FlushCharacters();
151 text_.Add(term);
152 } else {
153 FlushText();
154 terms_.Add(term);
155 }
156 LAST(ADD_ATOM);
157}
158
159
160void RegExpBuilder::AddAssertion(RegExpTree* assert) {
161 FlushText();
162 terms_.Add(assert);
163 LAST(ADD_ASSERT);
164}
165
166
167void RegExpBuilder::NewAlternative() {
168 FlushTerms();
169}
170
171
172void RegExpBuilder::FlushTerms() {
173 FlushText();
174 int num_terms = terms_.length();
175 RegExpTree* alternative;
176 if (num_terms == 0) {
177 alternative = RegExpEmpty::GetInstance();
178 } else if (num_terms == 1) {
179 alternative = terms_.last();
180 } else {
181 alternative = new RegExpAlternative(terms_.GetList());
182 }
183 alternatives_.Add(alternative);
184 terms_.Clear();
185 LAST(ADD_NONE);
186}
187
188
189RegExpTree* RegExpBuilder::ToRegExp() {
190 FlushTerms();
191 int num_alternatives = alternatives_.length();
192 if (num_alternatives == 0) {
193 return RegExpEmpty::GetInstance();
194 }
195 if (num_alternatives == 1) {
196 return alternatives_.last();
197 }
198 return new RegExpDisjunction(alternatives_.GetList());
199}
200
201
Leon Clarkee46be812010-01-19 14:06:41 +0000202void RegExpBuilder::AddQuantifierToAtom(int min,
203 int max,
204 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (pending_empty_) {
206 pending_empty_ = false;
207 return;
208 }
209 RegExpTree* atom;
210 if (characters_ != NULL) {
211 ASSERT(last_added_ == ADD_CHAR);
212 // Last atom was character.
213 Vector<const uc16> char_vector = characters_->ToConstVector();
214 int num_chars = char_vector.length();
215 if (num_chars > 1) {
216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
217 text_.Add(new RegExpAtom(prefix));
218 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219 }
220 characters_ = NULL;
221 atom = new RegExpAtom(char_vector);
222 FlushText();
223 } else if (text_.length() > 0) {
224 ASSERT(last_added_ == ADD_ATOM);
225 atom = text_.RemoveLast();
226 FlushText();
227 } else if (terms_.length() > 0) {
228 ASSERT(last_added_ == ADD_ATOM);
229 atom = terms_.RemoveLast();
230 if (atom->max_match() == 0) {
231 // Guaranteed to only match an empty string.
232 LAST(ADD_TERM);
233 if (min == 0) {
234 return;
235 }
236 terms_.Add(atom);
237 return;
238 }
239 } else {
240 // Only call immediately after adding an atom or character!
241 UNREACHABLE();
242 return;
243 }
Leon Clarkee46be812010-01-19 14:06:41 +0000244 terms_.Add(new RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 LAST(ADD_TERM);
246}
247
248
Steve Blocka7e24c12009-10-30 11:49:00 +0000249// A temporary scope stores information during parsing, just like
250// a plain scope. However, temporary scopes are not kept around
251// after parsing or referenced by syntax trees so they can be stack-
252// allocated and hence used by the pre-parser.
253class TemporaryScope BASE_EMBEDDED {
254 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800255 explicit TemporaryScope(TemporaryScope** variable);
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 ~TemporaryScope();
257
258 int NextMaterializedLiteralIndex() {
259 int next_index =
260 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
261 materialized_literal_count_++;
262 return next_index;
263 }
264 int materialized_literal_count() { return materialized_literal_count_; }
265
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 void SetThisPropertyAssignmentInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000267 bool only_simple_this_property_assignments,
268 Handle<FixedArray> this_property_assignments) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000269 only_simple_this_property_assignments_ =
270 only_simple_this_property_assignments;
271 this_property_assignments_ = this_property_assignments;
272 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 bool only_simple_this_property_assignments() {
274 return only_simple_this_property_assignments_;
275 }
276 Handle<FixedArray> this_property_assignments() {
277 return this_property_assignments_;
278 }
279
280 void AddProperty() { expected_property_count_++; }
281 int expected_property_count() { return expected_property_count_; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100282
283 void AddLoop() { loop_count_++; }
284 bool ContainsLoops() const { return loop_count_ > 0; }
285
Steve Block1e0659c2011-05-24 12:43:12 +0100286 bool StrictMode() { return strict_mode_; }
287 void EnableStrictMode() {
288 strict_mode_ = FLAG_strict_mode;
289 }
290
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 private:
Steve Block3ce2e202009-11-05 08:53:23 +0000292 // Captures the number of literals that need materialization in the
293 // function. Includes regexp literals, and boilerplate for object
294 // and array literals.
Steve Blocka7e24c12009-10-30 11:49:00 +0000295 int materialized_literal_count_;
296
Steve Blocka7e24c12009-10-30 11:49:00 +0000297 // Properties count estimation.
298 int expected_property_count_;
299
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100300 // Keeps track of assignments to properties of this. Used for
301 // optimizing constructors.
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 bool only_simple_this_property_assignments_;
303 Handle<FixedArray> this_property_assignments_;
304
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100305 // Captures the number of loops inside the scope.
306 int loop_count_;
307
Steve Block1e0659c2011-05-24 12:43:12 +0100308 // Parsing strict mode code.
309 bool strict_mode_;
310
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 // Bookkeeping
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800312 TemporaryScope** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 TemporaryScope* parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000314};
315
316
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800317TemporaryScope::TemporaryScope(TemporaryScope** variable)
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 : materialized_literal_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 expected_property_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000320 only_simple_this_property_assignments_(false),
321 this_property_assignments_(Factory::empty_fixed_array()),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100322 loop_count_(0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800323 variable_(variable),
324 parent_(*variable) {
Steve Block1e0659c2011-05-24 12:43:12 +0100325 // Inherit the strict mode from the parent scope.
326 strict_mode_ = (parent_ != NULL) && parent_->strict_mode_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800327 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000328}
329
330
331TemporaryScope::~TemporaryScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800332 *variable_ = parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000333}
334
335
Steve Block9fac8402011-05-12 15:51:54 +0100336Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800337 // Length of symbol cache is the number of identified symbols.
338 // If we are larger than that, or negative, it's not a cached symbol.
339 // This might also happen if there is no preparser symbol data, even
340 // if there is some preparser data.
341 if (static_cast<unsigned>(symbol_id)
342 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100343 if (scanner().is_literal_ascii()) {
344 return Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
345 } else {
346 return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
347 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800348 }
Steve Block9fac8402011-05-12 15:51:54 +0100349 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800350}
351
352
Steve Block9fac8402011-05-12 15:51:54 +0100353Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800354 // Make sure the cache is large enough to hold the symbol identifier.
355 if (symbol_cache_.length() <= symbol_id) {
356 // Increase length to index + 1.
357 symbol_cache_.AddBlock(Handle<String>::null(),
358 symbol_id + 1 - symbol_cache_.length());
359 }
360 Handle<String> result = symbol_cache_.at(symbol_id);
361 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100362 if (scanner().is_literal_ascii()) {
363 result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
364 } else {
365 result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
366 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800367 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100368 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800370 Counters::total_preparse_symbols_skipped.Increment();
371 return result;
372}
Steve Blocka7e24c12009-10-30 11:49:00 +0000373
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800374
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100375FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
376 // The current pre-data entry must be a FunctionEntry with the given
377 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100378 if ((function_index_ + FunctionEntry::kSize <= store_.length())
379 && (static_cast<int>(store_[function_index_]) == start)) {
380 int index = function_index_;
381 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100382 return FunctionEntry(store_.SubVector(index,
383 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 }
385 return FunctionEntry();
386}
387
388
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100389int ScriptDataImpl::GetSymbolIdentifier() {
390 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100391}
392
393
Iain Merrick9ac36c92010-09-13 15:29:50 +0100394bool ScriptDataImpl::SanityCheck() {
395 // Check that the header data is valid and doesn't specify
396 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800397 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
398 if (magic() != PreparseDataConstants::kMagicNumber) return false;
399 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100400 if (has_error()) {
401 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800402 if (store_.length() <= PreparseDataConstants::kHeaderSize
403 + PreparseDataConstants::kMessageTextPos) {
404 return false;
405 }
406 if (Read(PreparseDataConstants::kMessageStartPos) >
407 Read(PreparseDataConstants::kMessageEndPos)) {
408 return false;
409 }
410 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
411 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100412 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800413 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
414 return false;
415 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100416 int length = static_cast<int>(Read(pos));
417 if (length < 0) return false;
418 pos += 1 + length;
419 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800420 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
421 return false;
422 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100423 return true;
424 }
425 // Check that the space allocated for function entries is sane.
426 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800427 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100428 if (functions_size < 0) return false;
429 if (functions_size % FunctionEntry::kSize != 0) return false;
430 // Check that the count of symbols is non-negative.
431 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800432 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100433 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100434 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100435 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800436 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100437 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 return true;
439}
440
441
Steve Block59151502010-09-22 15:07:15 +0100442
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100443const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 int length = start[0];
445 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100446 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100448 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 result[length] = '\0';
450 if (chars != NULL) *chars = length;
451 return result;
452}
453
Steve Blocka7e24c12009-10-30 11:49:00 +0000454Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800455 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
456 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 return Scanner::Location(beg_pos, end_pos);
458}
459
460
461const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800462 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100463 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000464}
465
466
467Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800468 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100470 // Position after text found by skipping past length field and
471 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800472 int pos = PreparseDataConstants::kMessageTextPos + 1
473 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 for (int i = 0; i < arg_count; i++) {
475 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100476 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000477 pos += count + 1;
478 }
479 return Vector<const char*>(array, arg_count);
480}
481
482
483unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800484 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000485}
486
487
488unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800489 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000490}
491
492
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800493Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 Scope* result = new Scope(parent, type);
495 result->Initialize(inside_with);
496 return result;
497}
498
Steve Blocka7e24c12009-10-30 11:49:00 +0000499// ----------------------------------------------------------------------------
500// Target is a support class to facilitate manipulation of the
501// Parser's target_stack_ (the stack of potential 'break' and
502// 'continue' statement targets). Upon construction, a new target is
503// added; it is removed upon destruction.
504
505class Target BASE_EMBEDDED {
506 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800507 Target(Target** variable, AstNode* node)
508 : variable_(variable), node_(node), previous_(*variable) {
509 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 }
511
512 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800513 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000514 }
515
516 Target* previous() { return previous_; }
517 AstNode* node() { return node_; }
518
519 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800520 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 AstNode* node_;
522 Target* previous_;
523};
524
525
526class TargetScope BASE_EMBEDDED {
527 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800528 explicit TargetScope(Target** variable)
529 : variable_(variable), previous_(*variable) {
530 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000531 }
532
533 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800534 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 }
536
537 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800538 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 Target* previous_;
540};
541
542
543// ----------------------------------------------------------------------------
544// LexicalScope is a support class to facilitate manipulation of the
545// Parser's scope stack. The constructor sets the parser's top scope
546// to the incoming scope, and the destructor resets it.
547
548class LexicalScope BASE_EMBEDDED {
549 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800550 LexicalScope(Scope** scope_variable,
551 int* with_nesting_level_variable,
552 Scope* scope)
553 : scope_variable_(scope_variable),
554 with_nesting_level_variable_(with_nesting_level_variable),
555 prev_scope_(*scope_variable),
556 prev_level_(*with_nesting_level_variable) {
557 *scope_variable = scope;
558 *with_nesting_level_variable = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000559 }
560
561 ~LexicalScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800562 (*scope_variable_)->Leave();
563 *scope_variable_ = prev_scope_;
564 *with_nesting_level_variable_ = prev_level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 }
566
567 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800568 Scope** scope_variable_;
569 int* with_nesting_level_variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000570 Scope* prev_scope_;
571 int prev_level_;
572};
573
Steve Blocka7e24c12009-10-30 11:49:00 +0000574// ----------------------------------------------------------------------------
575// The CHECK_OK macro is a convenient macro to enforce error
576// handling for functions that may fail (by returning !*ok).
577//
578// CAUTION: This macro appends extra statements after a call,
579// thus it must never be used where only a single statement
580// is correct (e.g. an if statement branch w/o braces)!
581
582#define CHECK_OK ok); \
583 if (!*ok) return NULL; \
584 ((void)0
585#define DUMMY ) // to make indentation work
586#undef DUMMY
587
588#define CHECK_FAILED /**/); \
589 if (failed_) return NULL; \
590 ((void)0
591#define DUMMY ) // to make indentation work
592#undef DUMMY
593
594// ----------------------------------------------------------------------------
595// Implementation of Parser
596
597Parser::Parser(Handle<Script> script,
598 bool allow_natives_syntax,
599 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000600 ScriptDataImpl* pre_data)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800601 : symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
602 script_(script),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100603 scanner_(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000604 top_scope_(NULL),
605 with_nesting_level_(0),
606 temp_scope_(NULL),
607 target_stack_(NULL),
608 allow_natives_syntax_(allow_natives_syntax),
609 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100610 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100611 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100612 stack_overflow_(false),
613 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100614 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000615}
616
617
Steve Blocka7e24c12009-10-30 11:49:00 +0000618FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Block1e0659c2011-05-24 12:43:12 +0100619 bool in_global_context,
620 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000621 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
622
623 HistogramTimerScope timer(&Counters::parse);
624 Counters::total_parse_size.Increment(source->length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100625 fni_ = new FuncNameInferrer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000626
627 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100628 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100629 if (source->IsExternalTwoByteString()) {
630 // Notice that the stream is destroyed at the end of the branch block.
631 // The last line of the blocks can't be moved outside, even though they're
632 // identical calls.
633 ExternalTwoByteStringUC16CharacterStream stream(
634 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100635 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100636 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100637 } else {
638 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100639 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100640 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100641 }
642}
643
644
645FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
646 bool in_global_context,
Steve Block1e0659c2011-05-24 12:43:12 +0100647 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100650 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000651
652 // Compute the parsing mode.
653 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
654 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
655
656 Scope::Type type =
657 in_global_context
658 ? Scope::GLOBAL_SCOPE
659 : Scope::EVAL_SCOPE;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800660 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000661
662 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800663 { Scope* scope = NewScope(top_scope_, type, inside_with());
664 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
665 scope);
666 TemporaryScope temp_scope(&this->temp_scope_);
Steve Block1e0659c2011-05-24 12:43:12 +0100667 if (strict_mode == kStrictMode) {
668 temp_scope.EnableStrictMode();
669 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800670 ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000671 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100672 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800673 ParseSourceElements(body, Token::EOS, &ok);
Steve Block1e0659c2011-05-24 12:43:12 +0100674 if (ok && temp_scope_->StrictMode()) {
675 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
676 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000677 if (ok) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800678 result = new FunctionLiteral(
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 no_name,
680 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800681 body,
Steve Blocka7e24c12009-10-30 11:49:00 +0000682 temp_scope.materialized_literal_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 temp_scope.expected_property_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000684 temp_scope.only_simple_this_property_assignments(),
685 temp_scope.this_property_assignments(),
686 0,
687 0,
688 source->length(),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100689 false,
Steve Block1e0659c2011-05-24 12:43:12 +0100690 temp_scope.ContainsLoops(),
691 temp_scope.StrictMode());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100692 } else if (stack_overflow_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000693 Top::StackOverflow();
694 }
695 }
696
697 // Make sure the target stack is empty.
698 ASSERT(target_stack_ == NULL);
699
700 // If there was a syntax error we have to get rid of the AST
701 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100702 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000703 return result;
704}
705
Ben Murdochf87a2032010-10-22 12:50:53 +0100706FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000707 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
708 HistogramTimerScope timer(&Counters::parse_lazy);
Ben Murdochf87a2032010-10-22 12:50:53 +0100709 Handle<String> source(String::cast(script_->source()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000710 Counters::total_parse_size.Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000711
Ben Murdochb0fe1622011-05-05 13:52:32 +0100712 // Initialize parser state.
713 source->TryFlatten();
714 if (source->IsExternalTwoByteString()) {
715 ExternalTwoByteStringUC16CharacterStream stream(
716 Handle<ExternalTwoByteString>::cast(source),
717 info->start_position(),
718 info->end_position());
719 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
720 return result;
721 } else {
722 GenericStringUC16CharacterStream stream(source,
723 info->start_position(),
724 info->end_position());
725 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
726 return result;
727 }
728}
729
730
731FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
732 UC16CharacterStream* source,
733 ZoneScope* zone_scope) {
Steve Block9fac8402011-05-12 15:51:54 +0100734 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100735 ASSERT(target_stack_ == NULL);
736
Ben Murdochf87a2032010-10-22 12:50:53 +0100737 Handle<String> name(String::cast(info->name()));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100738 fni_ = new FuncNameInferrer();
739 fni_->PushEnclosingName(name);
740
Steve Blocka7e24c12009-10-30 11:49:00 +0000741 mode_ = PARSE_EAGERLY;
742
743 // Place holder for the result.
744 FunctionLiteral* result = NULL;
745
746 {
747 // Parse the function literal.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800748 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000749 Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800750 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
751 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
752 scope);
753 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000754
Steve Block1e0659c2011-05-24 12:43:12 +0100755 if (info->strict_mode()) {
756 temp_scope.EnableStrictMode();
757 }
758
Ben Murdochf87a2032010-10-22 12:50:53 +0100759 FunctionLiteralType type =
760 info->is_expression() ? EXPRESSION : DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000761 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100762 result = ParseFunctionLiteral(name,
763 false, // Strict mode name already checked.
764 RelocInfo::kNoPosition, type, &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000765 // Make sure the results agree.
766 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000767 }
768
769 // Make sure the target stack is empty.
770 ASSERT(target_stack_ == NULL);
771
772 // If there was a stack overflow we have to get rid of AST and it is
773 // not safe to do before scope has been deleted.
774 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100775 zone_scope->DeleteOnExit();
Steve Block1e0659c2011-05-24 12:43:12 +0100776 if (stack_overflow_) Top::StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100777 } else {
778 Handle<String> inferred_name(info->inferred_name());
779 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 }
781 return result;
782}
783
Ben Murdochf87a2032010-10-22 12:50:53 +0100784
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800785Handle<String> Parser::GetSymbol(bool* ok) {
786 int symbol_id = -1;
787 if (pre_data() != NULL) {
788 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000789 }
Steve Block9fac8402011-05-12 15:51:54 +0100790 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000791}
Steve Blocka7e24c12009-10-30 11:49:00 +0000792
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800793
Steve Blocka7e24c12009-10-30 11:49:00 +0000794void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100795 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000796 ReportMessageAt(source_location, type, args);
797}
798
799
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800800void Parser::ReportMessageAt(Scanner::Location source_location,
801 const char* type,
802 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000803 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100804 source_location.beg_pos,
805 source_location.end_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000806 Handle<JSArray> array = Factory::NewJSArray(args.length());
807 for (int i = 0; i < args.length(); i++) {
808 SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i])));
809 }
810 Handle<Object> result = Factory::NewSyntaxError(type, array);
811 Top::Throw(*result, &location);
812}
813
814
Ben Murdochb8e0da22011-05-16 14:20:40 +0100815void Parser::ReportMessageAt(Scanner::Location source_location,
816 const char* type,
817 Vector<Handle<String> > args) {
818 MessageLocation location(script_,
819 source_location.beg_pos,
820 source_location.end_pos);
821 Handle<JSArray> array = Factory::NewJSArray(args.length());
822 for (int i = 0; i < args.length(); i++) {
823 SetElement(array, i, args[i]);
824 }
825 Handle<Object> result = Factory::NewSyntaxError(type, array);
826 Top::Throw(*result, &location);
827}
828
829
Steve Blocka7e24c12009-10-30 11:49:00 +0000830// Base class containing common code for the different finder classes used by
831// the parser.
832class ParserFinder {
833 protected:
834 ParserFinder() {}
835 static Assignment* AsAssignment(Statement* stat) {
836 if (stat == NULL) return NULL;
837 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
838 if (exp_stat == NULL) return NULL;
839 return exp_stat->expression()->AsAssignment();
840 }
841};
842
843
844// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000845// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000846class InitializationBlockFinder : public ParserFinder {
847 public:
848 InitializationBlockFinder()
849 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
850
851 ~InitializationBlockFinder() {
852 if (InBlock()) EndBlock();
853 }
854
855 void Update(Statement* stat) {
856 Assignment* assignment = AsAssignment(stat);
857 if (InBlock()) {
858 if (BlockContinues(assignment)) {
859 UpdateBlock(assignment);
860 } else {
861 EndBlock();
862 }
863 }
864 if (!InBlock() && (assignment != NULL) &&
865 (assignment->op() == Token::ASSIGN)) {
866 StartBlock(assignment);
867 }
868 }
869
870 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800871 // The minimum number of contiguous assignment that will
872 // be treated as an initialization block. Benchmarks show that
873 // the overhead exceeds the savings below this limit.
874 static const int kMinInitializationBlock = 3;
875
Steve Blocka7e24c12009-10-30 11:49:00 +0000876 // Returns true if the expressions appear to denote the same object.
877 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000878 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000879 static bool SameObject(Expression* e1, Expression* e2) {
880 VariableProxy* v1 = e1->AsVariableProxy();
881 VariableProxy* v2 = e2->AsVariableProxy();
882 if (v1 != NULL && v2 != NULL) {
883 return v1->name()->Equals(*v2->name());
884 }
885 Property* p1 = e1->AsProperty();
886 Property* p2 = e2->AsProperty();
887 if ((p1 == NULL) || (p2 == NULL)) return false;
888 Literal* key1 = p1->key()->AsLiteral();
889 Literal* key2 = p2->key()->AsLiteral();
890 if ((key1 == NULL) || (key2 == NULL)) return false;
891 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
892 return false;
893 }
894 String* name1 = String::cast(*key1->handle());
895 String* name2 = String::cast(*key2->handle());
896 if (!name1->Equals(name2)) return false;
897 return SameObject(p1->obj(), p2->obj());
898 }
899
900 // Returns true if the expressions appear to denote different properties
901 // of the same object.
902 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
903 Property* p1 = e1->AsProperty();
904 Property* p2 = e2->AsProperty();
905 if ((p1 == NULL) || (p2 == NULL)) return false;
906 return SameObject(p1->obj(), p2->obj());
907 }
908
909 bool BlockContinues(Assignment* assignment) {
910 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
911 if (assignment->op() != Token::ASSIGN) return false;
912 return PropertyOfSameObject(first_in_block_->target(),
913 assignment->target());
914 }
915
916 void StartBlock(Assignment* assignment) {
917 first_in_block_ = assignment;
918 last_in_block_ = assignment;
919 block_size_ = 1;
920 }
921
922 void UpdateBlock(Assignment* assignment) {
923 last_in_block_ = assignment;
924 ++block_size_;
925 }
926
927 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800928 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 first_in_block_->mark_block_start();
930 last_in_block_->mark_block_end();
931 }
932 last_in_block_ = first_in_block_ = NULL;
933 block_size_ = 0;
934 }
935
936 bool InBlock() { return first_in_block_ != NULL; }
937
938 Assignment* first_in_block_;
939 Assignment* last_in_block_;
940 int block_size_;
941
942 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
943};
944
945
946// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
947// this.x = ...;, where x is a named property. It also determines whether a
948// function contains only assignments of this type.
949class ThisNamedPropertyAssigmentFinder : public ParserFinder {
950 public:
951 ThisNamedPropertyAssigmentFinder()
Steve Blockd0582a62009-12-15 09:54:21 +0000952 : only_simple_this_property_assignments_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 names_(NULL),
954 assigned_arguments_(NULL),
955 assigned_constants_(NULL) {}
956
957 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000958 // Bail out if function already has property assignment that are
959 // not simple this property assignments.
960 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000961 return;
962 }
963
964 // Check whether this statement is of the form this.x = ...;
965 Assignment* assignment = AsAssignment(stat);
966 if (IsThisPropertyAssignment(assignment)) {
967 HandleThisPropertyAssignment(scope, assignment);
968 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000969 only_simple_this_property_assignments_ = false;
970 }
971 }
972
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 // Returns whether only statements of the form this.x = y; where y is either a
974 // constant or a function argument was encountered.
975 bool only_simple_this_property_assignments() {
976 return only_simple_this_property_assignments_;
977 }
978
979 // Returns a fixed array containing three elements for each assignment of the
980 // form this.x = y;
981 Handle<FixedArray> GetThisPropertyAssignments() {
982 if (names_ == NULL) {
983 return Factory::empty_fixed_array();
984 }
985 ASSERT(names_ != NULL);
986 ASSERT(assigned_arguments_ != NULL);
987 ASSERT_EQ(names_->length(), assigned_arguments_->length());
988 ASSERT_EQ(names_->length(), assigned_constants_->length());
989 Handle<FixedArray> assignments =
990 Factory::NewFixedArray(names_->length() * 3);
991 for (int i = 0; i < names_->length(); i++) {
992 assignments->set(i * 3, *names_->at(i));
993 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
994 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
995 }
996 return assignments;
997 }
998
999 private:
1000 bool IsThisPropertyAssignment(Assignment* assignment) {
1001 if (assignment != NULL) {
1002 Property* property = assignment->target()->AsProperty();
1003 return assignment->op() == Token::ASSIGN
1004 && property != NULL
1005 && property->obj()->AsVariableProxy() != NULL
1006 && property->obj()->AsVariableProxy()->is_this();
1007 }
1008 return false;
1009 }
1010
1011 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +01001012 // Check that the property assigned to is a named property, which is not
1013 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +00001014 Property* property = assignment->target()->AsProperty();
1015 ASSERT(property != NULL);
1016 Literal* literal = property->key()->AsLiteral();
1017 uint32_t dummy;
1018 if (literal != NULL &&
1019 literal->handle()->IsString() &&
Steve Block6ded16b2010-05-10 14:33:55 +01001020 !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1022 Handle<String> key = Handle<String>::cast(literal->handle());
1023
1024 // Check whether the value assigned is either a constant or matches the
1025 // name of one of the arguments to the function.
1026 if (assignment->value()->AsLiteral() != NULL) {
1027 // Constant assigned.
1028 Literal* literal = assignment->value()->AsLiteral();
1029 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001030 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001031 } else if (assignment->value()->AsVariableProxy() != NULL) {
1032 // Variable assigned.
1033 Handle<String> name =
1034 assignment->value()->AsVariableProxy()->name();
1035 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 for (int i = 0; i < scope->num_parameters(); i++) {
1037 if (*scope->parameter(i)->name() == *name) {
1038 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001039 AssignmentFromParameter(key, i);
1040 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001041 }
1042 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001043 }
1044 }
Steve Blockd0582a62009-12-15 09:54:21 +00001045 // It is not a simple "this.x = value;" assignment with a constant
1046 // or parameter value.
1047 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001048 }
1049
1050 void AssignmentFromParameter(Handle<String> name, int index) {
1051 EnsureAllocation();
1052 names_->Add(name);
1053 assigned_arguments_->Add(index);
1054 assigned_constants_->Add(Factory::undefined_value());
1055 }
1056
1057 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
1058 EnsureAllocation();
1059 names_->Add(name);
1060 assigned_arguments_->Add(-1);
1061 assigned_constants_->Add(value);
1062 }
1063
Steve Blockd0582a62009-12-15 09:54:21 +00001064 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001065 // The this assignment is not a simple one.
1066 only_simple_this_property_assignments_ = false;
1067 }
1068
1069 void EnsureAllocation() {
1070 if (names_ == NULL) {
1071 ASSERT(assigned_arguments_ == NULL);
1072 ASSERT(assigned_constants_ == NULL);
1073 names_ = new ZoneStringList(4);
1074 assigned_arguments_ = new ZoneList<int>(4);
1075 assigned_constants_ = new ZoneObjectList(4);
1076 }
1077 }
1078
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 bool only_simple_this_property_assignments_;
1080 ZoneStringList* names_;
1081 ZoneList<int>* assigned_arguments_;
1082 ZoneObjectList* assigned_constants_;
1083};
1084
1085
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001086void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001087 int end_token,
1088 bool* ok) {
1089 // SourceElements ::
1090 // (Statement)* <end_token>
1091
1092 // Allocate a target stack to use for this set of source
1093 // elements. This way, all scripts and functions get their own
1094 // target stack thus avoiding illegal breaks and continues across
1095 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001096 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001097
1098 ASSERT(processor != NULL);
1099 InitializationBlockFinder block_finder;
1100 ThisNamedPropertyAssigmentFinder this_property_assignment_finder;
Steve Block1e0659c2011-05-24 12:43:12 +01001101 bool directive_prologue = true; // Parsing directive prologue.
1102
Steve Blocka7e24c12009-10-30 11:49:00 +00001103 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001104 if (directive_prologue && peek() != Token::STRING) {
1105 directive_prologue = false;
1106 }
1107
1108 Scanner::Location token_loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00001109 Statement* stat = ParseStatement(NULL, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001110
1111 if (stat == NULL || stat->IsEmpty()) {
1112 directive_prologue = false; // End of directive prologue.
1113 continue;
1114 }
1115
1116 if (directive_prologue) {
1117 // A shot at a directive.
1118 ExpressionStatement *e_stat;
1119 Literal *literal;
1120 // Still processing directive prologue?
1121 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1122 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1123 literal->handle()->IsString()) {
1124 Handle<String> directive = Handle<String>::cast(literal->handle());
1125
1126 // Check "use strict" directive (ES5 14.1).
1127 if (!temp_scope_->StrictMode() &&
1128 directive->Equals(Heap::use_strict()) &&
1129 token_loc.end_pos - token_loc.beg_pos ==
1130 Heap::use_strict()->length() + 2) {
1131 temp_scope_->EnableStrictMode();
1132 // "use strict" is the only directive for now.
1133 directive_prologue = false;
1134 }
1135 } else {
1136 // End of the directive prologue.
1137 directive_prologue = false;
1138 }
1139 }
1140
Steve Blocka7e24c12009-10-30 11:49:00 +00001141 // We find and mark the initialization blocks on top level code only.
1142 // This is because the optimization prevents reuse of the map transitions,
1143 // so it should be used only for code that will only be run once.
1144 if (top_scope_->is_global_scope()) {
1145 block_finder.Update(stat);
1146 }
1147 // Find and mark all assignments to named properties in this (this.x =)
1148 if (top_scope_->is_function_scope()) {
1149 this_property_assignment_finder.Update(top_scope_, stat);
1150 }
1151 processor->Add(stat);
1152 }
1153
1154 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001155 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001156 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001157 this_property_assignment_finder.only_simple_this_property_assignments()
1158 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001159 if (only_simple_this_property_assignments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001160 temp_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001161 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001162 this_property_assignment_finder.GetThisPropertyAssignments());
1163 }
1164 }
1165 return 0;
1166}
1167
1168
1169Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1170 // Statement ::
1171 // Block
1172 // VariableStatement
1173 // EmptyStatement
1174 // ExpressionStatement
1175 // IfStatement
1176 // IterationStatement
1177 // ContinueStatement
1178 // BreakStatement
1179 // ReturnStatement
1180 // WithStatement
1181 // LabelledStatement
1182 // SwitchStatement
1183 // ThrowStatement
1184 // TryStatement
1185 // DebuggerStatement
1186
1187 // Note: Since labels can only be used by 'break' and 'continue'
1188 // statements, which themselves are only valid within blocks,
1189 // iterations or 'switch' statements (i.e., BreakableStatements),
1190 // labels can be simply ignored in all other cases; except for
1191 // trivial labeled break statements 'label: break label' which is
1192 // parsed into an empty statement.
1193
1194 // Keep the source position of the statement
1195 int statement_pos = scanner().peek_location().beg_pos;
1196 Statement* stmt = NULL;
1197 switch (peek()) {
1198 case Token::LBRACE:
1199 return ParseBlock(labels, ok);
1200
1201 case Token::CONST: // fall through
1202 case Token::VAR:
1203 stmt = ParseVariableStatement(ok);
1204 break;
1205
1206 case Token::SEMICOLON:
1207 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001208 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001209
1210 case Token::IF:
1211 stmt = ParseIfStatement(labels, ok);
1212 break;
1213
1214 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001215 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001216 break;
1217
1218 case Token::WHILE:
1219 stmt = ParseWhileStatement(labels, ok);
1220 break;
1221
1222 case Token::FOR:
1223 stmt = ParseForStatement(labels, ok);
1224 break;
1225
1226 case Token::CONTINUE:
1227 stmt = ParseContinueStatement(ok);
1228 break;
1229
1230 case Token::BREAK:
1231 stmt = ParseBreakStatement(labels, ok);
1232 break;
1233
1234 case Token::RETURN:
1235 stmt = ParseReturnStatement(ok);
1236 break;
1237
1238 case Token::WITH:
1239 stmt = ParseWithStatement(labels, ok);
1240 break;
1241
1242 case Token::SWITCH:
1243 stmt = ParseSwitchStatement(labels, ok);
1244 break;
1245
1246 case Token::THROW:
1247 stmt = ParseThrowStatement(ok);
1248 break;
1249
1250 case Token::TRY: {
1251 // NOTE: It is somewhat complicated to have labels on
1252 // try-statements. When breaking out of a try-finally statement,
1253 // one must take great care not to treat it as a
1254 // fall-through. It is much easier just to wrap the entire
1255 // try-statement in a statement block and put the labels there
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001256 Block* result = new Block(labels, 1, false);
1257 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001258 TryStatement* statement = ParseTryStatement(CHECK_OK);
1259 if (statement) {
1260 statement->set_statement_pos(statement_pos);
1261 }
1262 if (result) result->AddStatement(statement);
1263 return result;
1264 }
1265
1266 case Token::FUNCTION:
1267 return ParseFunctionDeclaration(ok);
1268
1269 case Token::NATIVE:
1270 return ParseNativeDeclaration(ok);
1271
1272 case Token::DEBUGGER:
1273 stmt = ParseDebuggerStatement(ok);
1274 break;
1275
1276 default:
1277 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1278 }
1279
1280 // Store the source position of the statement
1281 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1282 return stmt;
1283}
1284
1285
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001286VariableProxy* Parser::Declare(Handle<String> name,
1287 Variable::Mode mode,
1288 FunctionLiteral* fun,
1289 bool resolve,
1290 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 Variable* var = NULL;
1292 // If we are inside a function, a declaration of a variable
1293 // is a truly local variable, and the scope of the variable
1294 // is always the function scope.
1295
1296 // If a function scope exists, then we can statically declare this
1297 // variable and also set its mode. In any case, a Declaration node
1298 // will be added to the scope so that the declaration can be added
1299 // to the corresponding activation frame at runtime if necessary.
1300 // For instance declarations inside an eval scope need to be added
1301 // to the calling function context.
1302 if (top_scope_->is_function_scope()) {
1303 // Declare the variable in the function scope.
1304 var = top_scope_->LocalLookup(name);
1305 if (var == NULL) {
1306 // Declare the name.
1307 var = top_scope_->DeclareLocal(name, mode);
1308 } else {
1309 // The name was declared before; check for conflicting
1310 // re-declarations. If the previous declaration was a const or the
1311 // current declaration is a const then we have a conflict. There is
1312 // similar code in runtime.cc in the Declare functions.
1313 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1314 // We only have vars and consts in declarations.
1315 ASSERT(var->mode() == Variable::VAR ||
1316 var->mode() == Variable::CONST);
1317 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1318 Handle<String> type_string =
1319 Factory::NewStringFromUtf8(CStrVector(type), TENURED);
1320 Expression* expression =
1321 NewThrowTypeError(Factory::redeclaration_symbol(),
1322 type_string, name);
1323 top_scope_->SetIllegalRedeclaration(expression);
1324 }
1325 }
1326 }
1327
1328 // We add a declaration node for every declaration. The compiler
1329 // will only generate code if necessary. In particular, declarations
1330 // for inner local variables that do not represent functions won't
1331 // result in any generated code.
1332 //
1333 // Note that we always add an unresolved proxy even if it's not
1334 // used, simply because we don't know in this method (w/o extra
1335 // parameters) if the proxy is needed or not. The proxy will be
1336 // bound during variable resolution time unless it was pre-bound
1337 // below.
1338 //
1339 // WARNING: This will lead to multiple declaration nodes for the
1340 // same variable if it is declared several times. This is not a
1341 // semantic issue as long as we keep the source order, but it may be
1342 // a performance issue since it may lead to repeated
1343 // Runtime::DeclareContextSlot() calls.
1344 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001345 top_scope_->AddDeclaration(new Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001346
1347 // For global const variables we bind the proxy to a variable.
1348 if (mode == Variable::CONST && top_scope_->is_global_scope()) {
1349 ASSERT(resolve); // should be set by all callers
1350 Variable::Kind kind = Variable::NORMAL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001351 var = new Variable(top_scope_, name, Variable::CONST, true, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 }
1353
1354 // If requested and we have a local variable, bind the proxy to the variable
1355 // at parse-time. This is used for functions (and consts) declared inside
1356 // statements: the corresponding function (or const) variable must be in the
1357 // function scope and not a statement-local scope, e.g. as provided with a
1358 // 'with' statement:
1359 //
1360 // with (obj) {
1361 // function f() {}
1362 // }
1363 //
1364 // which is translated into:
1365 //
1366 // with (obj) {
1367 // // in this case this is not: 'var f; f = function () {};'
1368 // var f = function () {};
1369 // }
1370 //
1371 // Note that if 'f' is accessed from inside the 'with' statement, it
1372 // will be allocated in the context (because we must be able to look
1373 // it up dynamically) but it will also be accessed statically, i.e.,
1374 // with a context slot index and a context chain length for this
1375 // initialization code. Thus, inside the 'with' statement, we need
1376 // both access to the static and the dynamic context chain; the
1377 // runtime needs to provide both.
1378 if (resolve && var != NULL) proxy->BindTo(var);
1379
1380 return proxy;
1381}
1382
1383
1384// Language extension which is only enabled for source files loaded
1385// through the API's extension mechanism. A native function
1386// declaration is resolved by looking up the function through a
1387// callback provided by the extension.
1388Statement* Parser::ParseNativeDeclaration(bool* ok) {
1389 if (extension_ == NULL) {
1390 ReportUnexpectedToken(Token::NATIVE);
1391 *ok = false;
1392 return NULL;
1393 }
1394
1395 Expect(Token::NATIVE, CHECK_OK);
1396 Expect(Token::FUNCTION, CHECK_OK);
1397 Handle<String> name = ParseIdentifier(CHECK_OK);
1398 Expect(Token::LPAREN, CHECK_OK);
1399 bool done = (peek() == Token::RPAREN);
1400 while (!done) {
1401 ParseIdentifier(CHECK_OK);
1402 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001403 if (!done) {
1404 Expect(Token::COMMA, CHECK_OK);
1405 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001406 }
1407 Expect(Token::RPAREN, CHECK_OK);
1408 Expect(Token::SEMICOLON, CHECK_OK);
1409
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 // Make sure that the function containing the native declaration
1411 // isn't lazily compiled. The extension structures are only
1412 // accessible while parsing the first time not when reparsing
1413 // because of lazy compilation.
1414 top_scope_->ForceEagerCompilation();
1415
1416 // Compute the function template for the native function.
1417 v8::Handle<v8::FunctionTemplate> fun_template =
1418 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1419 ASSERT(!fun_template.IsEmpty());
1420
Steve Block6ded16b2010-05-10 14:33:55 +01001421 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001422 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1423 const int literals = fun->NumberOfLiterals();
1424 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001425 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001426 Handle<SharedFunctionInfo> shared =
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001427 Factory::NewSharedFunctionInfo(name, literals, code,
1428 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001429 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001430
Steve Block6ded16b2010-05-10 14:33:55 +01001431 // Copy the function data to the shared function info.
1432 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001433 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001434 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001435
1436 // TODO(1240846): It's weird that native function declarations are
1437 // introduced dynamically when we meet their declarations, whereas
1438 // other functions are setup when entering the surrounding scope.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001439 SharedFunctionInfoLiteral* lit = new SharedFunctionInfoLiteral(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001440 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001441 return new ExpressionStatement(
1442 new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001443}
1444
1445
1446Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1447 // FunctionDeclaration ::
1448 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1449 Expect(Token::FUNCTION, CHECK_OK);
1450 int function_token_position = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01001451 bool is_reserved = false;
1452 Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 FunctionLiteral* fun = ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01001454 is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001455 function_token_position,
1456 DECLARATION,
1457 CHECK_OK);
1458 // Even if we're not at the top-level of the global or a function
1459 // scope, we treat is as such and introduce the function with it's
1460 // initial value upon entering the corresponding scope.
1461 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001462 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001463}
1464
1465
1466Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1467 // Block ::
1468 // '{' Statement* '}'
1469
1470 // Note that a Block does not introduce a new execution scope!
1471 // (ECMA-262, 3rd, 12.2)
1472 //
1473 // Construct block expecting 16 statements.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001474 Block* result = new Block(labels, 16, false);
1475 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001476 Expect(Token::LBRACE, CHECK_OK);
1477 while (peek() != Token::RBRACE) {
1478 Statement* stat = ParseStatement(NULL, CHECK_OK);
1479 if (stat && !stat->IsEmpty()) result->AddStatement(stat);
1480 }
1481 Expect(Token::RBRACE, CHECK_OK);
1482 return result;
1483}
1484
1485
1486Block* Parser::ParseVariableStatement(bool* ok) {
1487 // VariableStatement ::
1488 // VariableDeclarations ';'
1489
1490 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature
1491 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK);
1492 ExpectSemicolon(CHECK_OK);
1493 return result;
1494}
1495
Steve Block1e0659c2011-05-24 12:43:12 +01001496static bool IsEvalOrArguments(Handle<String> string) {
1497 return string.is_identical_to(Factory::eval_symbol()) ||
1498 string.is_identical_to(Factory::arguments_symbol());
1499}
Steve Blocka7e24c12009-10-30 11:49:00 +00001500
1501// If the variable declaration declares exactly one non-const
1502// variable, then *var is set to that variable. In all other cases,
1503// *var is untouched; in particular, it is the caller's responsibility
1504// to initialize it properly. This mechanism is used for the parsing
1505// of 'for-in' loops.
1506Block* Parser::ParseVariableDeclarations(bool accept_IN,
1507 Expression** var,
1508 bool* ok) {
1509 // VariableDeclarations ::
1510 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1511
1512 Variable::Mode mode = Variable::VAR;
1513 bool is_const = false;
1514 if (peek() == Token::VAR) {
1515 Consume(Token::VAR);
1516 } else if (peek() == Token::CONST) {
1517 Consume(Token::CONST);
1518 mode = Variable::CONST;
1519 is_const = true;
1520 } else {
1521 UNREACHABLE(); // by current callers
1522 }
1523
1524 // The scope of a variable/const declared anywhere inside a function
1525 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1526 // transform a source-level variable/const declaration into a (Function)
1527 // Scope declaration, and rewrite the source-level initialization into an
1528 // assignment statement. We use a block to collect multiple assignments.
1529 //
1530 // We mark the block as initializer block because we don't want the
1531 // rewriter to add a '.result' assignment to such a block (to get compliant
1532 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1533 // reasons when pretty-printing. Also, unless an assignment (initialization)
1534 // is inside an initializer block, it is ignored.
1535 //
1536 // Create new block with one expected declaration.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001537 Block* block = new Block(NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001538 VariableProxy* last_var = NULL; // the last variable declared
1539 int nvars = 0; // the number of variables declared
1540 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001541 if (fni_ != NULL) fni_->Enter();
1542
Steve Blocka7e24c12009-10-30 11:49:00 +00001543 // Parse variable name.
1544 if (nvars > 0) Consume(Token::COMMA);
1545 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001546 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001547
Steve Block1e0659c2011-05-24 12:43:12 +01001548 // Strict mode variables may not be named eval or arguments
1549 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
1550 ReportMessage("strict_var_name", Vector<const char*>::empty());
1551 *ok = false;
1552 return NULL;
1553 }
1554
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 // Declare variable.
1556 // Note that we *always* must treat the initial value via a separate init
1557 // assignment for variables and constants because the value must be assigned
1558 // when the variable is encountered in the source. But the variable/constant
1559 // is declared (and set to 'undefined') upon entering the function within
1560 // which the variable or constant is declared. Only function variables have
1561 // an initial value in the declaration (because they are initialized upon
1562 // entering the function).
1563 //
1564 // If we have a const declaration, in an inner scope, the proxy is always
1565 // bound to the declared variable (independent of possibly surrounding with
1566 // statements).
1567 last_var = Declare(name, mode, NULL,
1568 is_const /* always bound for CONST! */,
1569 CHECK_OK);
1570 nvars++;
1571
1572 // Parse initialization expression if present and/or needed. A
1573 // declaration of the form:
1574 //
1575 // var v = x;
1576 //
1577 // is syntactic sugar for:
1578 //
1579 // var v; v = x;
1580 //
1581 // In particular, we need to re-lookup 'v' as it may be a
1582 // different 'v' than the 'v' in the declaration (if we are inside
1583 // a 'with' statement that makes a object property with name 'v'
1584 // visible).
1585 //
1586 // However, note that const declarations are different! A const
1587 // declaration of the form:
1588 //
1589 // const c = x;
1590 //
1591 // is *not* syntactic sugar for:
1592 //
1593 // const c; c = x;
1594 //
1595 // The "variable" c initialized to x is the same as the declared
1596 // one - there is no re-lookup (see the last parameter of the
1597 // Declare() call above).
1598
1599 Expression* value = NULL;
1600 int position = -1;
1601 if (peek() == Token::ASSIGN) {
1602 Expect(Token::ASSIGN, CHECK_OK);
1603 position = scanner().location().beg_pos;
1604 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001605 // Don't infer if it is "a = function(){...}();"-like expression.
1606 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer();
Steve Blocka7e24c12009-10-30 11:49:00 +00001607 }
1608
1609 // Make sure that 'const c' actually initializes 'c' to undefined
1610 // even though it seems like a stupid thing to do.
1611 if (value == NULL && is_const) {
1612 value = GetLiteralUndefined();
1613 }
1614
1615 // Global variable declarations must be compiled in a specific
1616 // way. When the script containing the global variable declaration
1617 // is entered, the global variable must be declared, so that if it
1618 // doesn't exist (not even in a prototype of the global object) it
1619 // gets created with an initial undefined value. This is handled
1620 // by the declarations part of the function representing the
1621 // top-level global code; see Runtime::DeclareGlobalVariable. If
1622 // it already exists (in the object or in a prototype), it is
1623 // *not* touched until the variable declaration statement is
1624 // executed.
1625 //
1626 // Executing the variable declaration statement will always
1627 // guarantee to give the global object a "local" variable; a
1628 // variable defined in the global object and not in any
1629 // prototype. This way, global variable declarations can shadow
1630 // properties in the prototype chain, but only after the variable
1631 // declaration statement has been executed. This is important in
1632 // browsers where the global object (window) has lots of
1633 // properties defined in prototype objects.
1634
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001635 if (top_scope_->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001636 // Compute the arguments for the runtime call.
1637 ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
1638 // Be careful not to assign a value to the global variable if
1639 // we're in a with. The initialization value should not
1640 // necessarily be stored in the global object in that case,
1641 // which is why we need to generate a separate assignment node.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001642 arguments->Add(new Literal(name)); // we have at least 1 parameter
Steve Blocka7e24c12009-10-30 11:49:00 +00001643 if (is_const || (value != NULL && !inside_with())) {
1644 arguments->Add(value);
1645 value = NULL; // zap the value to avoid the unnecessary assignment
1646 }
1647 // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
1648 // and add it to the initialization statement block. Note that
1649 // this function does different things depending on if we have
1650 // 1 or 2 parameters.
1651 CallRuntime* initialize;
1652 if (is_const) {
1653 initialize =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001654 new CallRuntime(
Steve Blocka7e24c12009-10-30 11:49:00 +00001655 Factory::InitializeConstGlobal_symbol(),
1656 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001657 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001658 } else {
1659 initialize =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001660 new CallRuntime(
Steve Blocka7e24c12009-10-30 11:49:00 +00001661 Factory::InitializeVarGlobal_symbol(),
1662 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001663 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001664 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001665 block->AddStatement(new ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001666 }
1667
1668 // Add an assignment node to the initialization statement block if
1669 // we still have a pending initialization value. We must distinguish
1670 // between variables and constants: Variable initializations are simply
1671 // assignments (with all the consequences if they are inside a 'with'
1672 // statement - they may change a 'with' object property). Constant
1673 // initializations always assign to the declared constant which is
1674 // always at the function scope level. This is only relevant for
1675 // dynamically looked-up variables and constants (the start context
1676 // for constant lookups is always the function context, while it is
1677 // the top context for variables). Sigh...
1678 if (value != NULL) {
1679 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001680 Assignment* assignment = new Assignment(op, last_var, value, position);
1681 if (block) block->AddStatement(new ExpressionStatement(assignment));
Steve Blocka7e24c12009-10-30 11:49:00 +00001682 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001683
1684 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001685 } while (peek() == Token::COMMA);
1686
1687 if (!is_const && nvars == 1) {
1688 // We have a single, non-const variable.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001689 ASSERT(last_var != NULL);
1690 *var = last_var;
Steve Blocka7e24c12009-10-30 11:49:00 +00001691 }
1692
1693 return block;
1694}
1695
1696
1697static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1698 ASSERT(!label.is_null());
1699 if (labels != NULL)
1700 for (int i = labels->length(); i-- > 0; )
1701 if (labels->at(i).is_identical_to(label))
1702 return true;
1703
1704 return false;
1705}
1706
1707
1708Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1709 bool* ok) {
1710 // ExpressionStatement | LabelledStatement ::
1711 // Expression ';'
1712 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001713 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001714 Expression* expr = ParseExpression(true, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001715 if (peek() == Token::COLON && starts_with_idenfifier && expr &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001716 expr->AsVariableProxy() != NULL &&
1717 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001718 // Expression is a single identifier, and not, e.g., a parenthesized
1719 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001720 VariableProxy* var = expr->AsVariableProxy();
1721 Handle<String> label = var->name();
1722 // TODO(1240780): We don't check for redeclaration of labels
1723 // during preparsing since keeping track of the set of active
1724 // labels requires nontrivial changes to the way scopes are
1725 // structured. However, these are probably changes we want to
1726 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001727 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1728 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1729 const char* elms[2] = { "Label", *c_string };
1730 Vector<const char*> args(elms, 2);
1731 ReportMessage("redeclaration", args);
1732 *ok = false;
1733 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001734 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001735 if (labels == NULL) labels = new ZoneStringList(4);
1736 labels->Add(label);
1737 // Remove the "ghost" variable that turned out to be a label
1738 // from the top scope. This way, we don't try to resolve it
1739 // during the scope processing.
1740 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001741 Expect(Token::COLON, CHECK_OK);
1742 return ParseStatement(labels, ok);
1743 }
1744
1745 // Parsed expression statement.
1746 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001747 return new ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001748}
1749
1750
1751IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1752 // IfStatement ::
1753 // 'if' '(' Expression ')' Statement ('else' Statement)?
1754
1755 Expect(Token::IF, CHECK_OK);
1756 Expect(Token::LPAREN, CHECK_OK);
1757 Expression* condition = ParseExpression(true, CHECK_OK);
1758 Expect(Token::RPAREN, CHECK_OK);
1759 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1760 Statement* else_statement = NULL;
1761 if (peek() == Token::ELSE) {
1762 Next();
1763 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001764 } else {
1765 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001766 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001767 return new IfStatement(condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001768}
1769
1770
1771Statement* Parser::ParseContinueStatement(bool* ok) {
1772 // ContinueStatement ::
1773 // 'continue' Identifier? ';'
1774
1775 Expect(Token::CONTINUE, CHECK_OK);
1776 Handle<String> label = Handle<String>::null();
1777 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001778 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001779 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1780 label = ParseIdentifier(CHECK_OK);
1781 }
1782 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001783 target = LookupContinueTarget(label, CHECK_OK);
1784 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001785 // Illegal continue statement.
1786 const char* message = "illegal_continue";
1787 Vector<Handle<String> > args;
1788 if (!label.is_null()) {
1789 message = "unknown_label";
1790 args = Vector<Handle<String> >(&label, 1);
1791 }
1792 ReportMessageAt(scanner().location(), message, args);
1793 *ok = false;
1794 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001795 }
1796 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001797 return new ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001798}
1799
1800
1801Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1802 // BreakStatement ::
1803 // 'break' Identifier? ';'
1804
1805 Expect(Token::BREAK, CHECK_OK);
1806 Handle<String> label;
1807 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001808 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001809 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1810 label = ParseIdentifier(CHECK_OK);
1811 }
1812 // Parse labeled break statements that target themselves into
1813 // empty statements, e.g. 'l1: l2: l3: break l2;'
1814 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001815 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001816 }
1817 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001818 target = LookupBreakTarget(label, CHECK_OK);
1819 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001820 // Illegal break statement.
1821 const char* message = "illegal_break";
1822 Vector<Handle<String> > args;
1823 if (!label.is_null()) {
1824 message = "unknown_label";
1825 args = Vector<Handle<String> >(&label, 1);
1826 }
1827 ReportMessageAt(scanner().location(), message, args);
1828 *ok = false;
1829 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001830 }
1831 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001832 return new BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001833}
1834
1835
1836Statement* Parser::ParseReturnStatement(bool* ok) {
1837 // ReturnStatement ::
1838 // 'return' Expression? ';'
1839
1840 // Consume the return token. It is necessary to do the before
1841 // reporting any errors on it, because of the way errors are
1842 // reported (underlining).
1843 Expect(Token::RETURN, CHECK_OK);
1844
1845 // An ECMAScript program is considered syntactically incorrect if it
1846 // contains a return statement that is not within the body of a
1847 // function. See ECMA-262, section 12.9, page 67.
1848 //
1849 // To be consistent with KJS we report the syntax error at runtime.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001850 if (!top_scope_->is_function_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001851 Handle<String> type = Factory::illegal_return_symbol();
1852 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001853 return new ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001854 }
1855
1856 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001857 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001858 tok == Token::SEMICOLON ||
1859 tok == Token::RBRACE ||
1860 tok == Token::EOS) {
1861 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001862 return new ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001863 }
1864
1865 Expression* expr = ParseExpression(true, CHECK_OK);
1866 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001867 return new ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001868}
1869
1870
1871Block* Parser::WithHelper(Expression* obj,
1872 ZoneStringList* labels,
1873 bool is_catch_block,
1874 bool* ok) {
1875 // Parse the statement and collect escaping labels.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001876 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001877 TargetCollector collector(target_list);
1878 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001879 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001880 with_nesting_level_++;
1881 top_scope_->RecordWithStatement();
1882 stat = ParseStatement(labels, CHECK_OK);
1883 with_nesting_level_--;
1884 }
1885 // Create resulting block with two statements.
1886 // 1: Evaluate the with expression.
1887 // 2: The try-finally block evaluating the body.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001888 Block* result = new Block(NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001889
1890 if (result != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001891 result->AddStatement(new WithEnterStatement(obj, is_catch_block));
Steve Blocka7e24c12009-10-30 11:49:00 +00001892
1893 // Create body block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001894 Block* body = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001895 body->AddStatement(stat);
1896
1897 // Create exit block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001898 Block* exit = new Block(NULL, 1, false);
1899 exit->AddStatement(new WithExitStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00001900
1901 // Return a try-finally statement.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001902 TryFinallyStatement* wrapper = new TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001903 wrapper->set_escaping_targets(collector.targets());
1904 result->AddStatement(wrapper);
1905 }
1906 return result;
1907}
1908
1909
1910Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
1911 // WithStatement ::
1912 // 'with' '(' Expression ')' Statement
1913
1914 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001915
1916 if (temp_scope_->StrictMode()) {
1917 ReportMessage("strict_mode_with", Vector<const char*>::empty());
1918 *ok = false;
1919 return NULL;
1920 }
1921
Steve Blocka7e24c12009-10-30 11:49:00 +00001922 Expect(Token::LPAREN, CHECK_OK);
1923 Expression* expr = ParseExpression(true, CHECK_OK);
1924 Expect(Token::RPAREN, CHECK_OK);
1925
1926 return WithHelper(expr, labels, false, CHECK_OK);
1927}
1928
1929
1930CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1931 // CaseClause ::
1932 // 'case' Expression ':' Statement*
1933 // 'default' ':' Statement*
1934
1935 Expression* label = NULL; // NULL expression indicates default case
1936 if (peek() == Token::CASE) {
1937 Expect(Token::CASE, CHECK_OK);
1938 label = ParseExpression(true, CHECK_OK);
1939 } else {
1940 Expect(Token::DEFAULT, CHECK_OK);
1941 if (*default_seen_ptr) {
1942 ReportMessage("multiple_defaults_in_switch",
1943 Vector<const char*>::empty());
1944 *ok = false;
1945 return NULL;
1946 }
1947 *default_seen_ptr = true;
1948 }
1949 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001950 int pos = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001951 ZoneList<Statement*>* statements = new ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001952 while (peek() != Token::CASE &&
1953 peek() != Token::DEFAULT &&
1954 peek() != Token::RBRACE) {
1955 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001956 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001957 }
1958
Ben Murdochb0fe1622011-05-05 13:52:32 +01001959 return new CaseClause(label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001960}
1961
1962
1963SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
1964 bool* ok) {
1965 // SwitchStatement ::
1966 // 'switch' '(' Expression ')' '{' CaseClause* '}'
1967
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001968 SwitchStatement* statement = new SwitchStatement(labels);
1969 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001970
1971 Expect(Token::SWITCH, CHECK_OK);
1972 Expect(Token::LPAREN, CHECK_OK);
1973 Expression* tag = ParseExpression(true, CHECK_OK);
1974 Expect(Token::RPAREN, CHECK_OK);
1975
1976 bool default_seen = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001977 ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001978 Expect(Token::LBRACE, CHECK_OK);
1979 while (peek() != Token::RBRACE) {
1980 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001981 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00001982 }
1983 Expect(Token::RBRACE, CHECK_OK);
1984
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001985 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00001986 return statement;
1987}
1988
1989
1990Statement* Parser::ParseThrowStatement(bool* ok) {
1991 // ThrowStatement ::
1992 // 'throw' Expression ';'
1993
1994 Expect(Token::THROW, CHECK_OK);
1995 int pos = scanner().location().beg_pos;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001996 if (scanner().has_line_terminator_before_next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001997 ReportMessage("newline_after_throw", Vector<const char*>::empty());
1998 *ok = false;
1999 return NULL;
2000 }
2001 Expression* exception = ParseExpression(true, CHECK_OK);
2002 ExpectSemicolon(CHECK_OK);
2003
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002004 return new ExpressionStatement(new Throw(exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002005}
2006
2007
2008TryStatement* Parser::ParseTryStatement(bool* ok) {
2009 // TryStatement ::
2010 // 'try' Block Catch
2011 // 'try' Block Finally
2012 // 'try' Block Catch Finally
2013 //
2014 // Catch ::
2015 // 'catch' '(' Identifier ')' Block
2016 //
2017 // Finally ::
2018 // 'finally' Block
2019
2020 Expect(Token::TRY, CHECK_OK);
2021
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002022 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002023 TargetCollector collector(target_list);
2024 Block* try_block;
2025
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002026 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002027 try_block = ParseBlock(NULL, CHECK_OK);
2028 }
2029
2030 Block* catch_block = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002031 Variable* catch_var = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002032 Block* finally_block = NULL;
2033
2034 Token::Value tok = peek();
2035 if (tok != Token::CATCH && tok != Token::FINALLY) {
2036 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2037 *ok = false;
2038 return NULL;
2039 }
2040
2041 // If we can break out from the catch block and there is a finally block,
2042 // then we will need to collect jump targets from the catch block. Since
2043 // we don't know yet if there will be a finally block, we always collect
2044 // the jump targets.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002045 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002046 TargetCollector catch_collector(catch_target_list);
2047 bool has_catch = false;
2048 if (tok == Token::CATCH) {
2049 has_catch = true;
2050 Consume(Token::CATCH);
2051
2052 Expect(Token::LPAREN, CHECK_OK);
2053 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002054
2055 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
2056 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2057 *ok = false;
2058 return NULL;
2059 }
2060
Steve Blocka7e24c12009-10-30 11:49:00 +00002061 Expect(Token::RPAREN, CHECK_OK);
2062
2063 if (peek() == Token::LBRACE) {
2064 // Allocate a temporary for holding the finally state while
2065 // executing the finally block.
2066 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002067 Literal* name_literal = new Literal(name);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002068 VariableProxy* catch_var_use = new VariableProxy(catch_var);
2069 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002070 { Target target(&this->target_stack_, &catch_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002071 catch_block = WithHelper(obj, NULL, true, CHECK_OK);
2072 }
2073 } else {
2074 Expect(Token::LBRACE, CHECK_OK);
2075 }
2076
2077 tok = peek();
2078 }
2079
2080 if (tok == Token::FINALLY || !has_catch) {
2081 Consume(Token::FINALLY);
2082 // Declare a variable for holding the finally state while
2083 // executing the finally block.
2084 finally_block = ParseBlock(NULL, CHECK_OK);
2085 }
2086
2087 // Simplify the AST nodes by converting:
2088 // 'try { } catch { } finally { }'
2089 // to:
2090 // 'try { try { } catch { } } finally { }'
2091
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002092 if (catch_block != NULL && finally_block != NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002093 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
Steve Block3ce2e202009-11-05 08:53:23 +00002094 TryCatchStatement* statement =
Ben Murdochb0fe1622011-05-05 13:52:32 +01002095 new TryCatchStatement(try_block, catch_var_defn, catch_block);
Steve Blocka7e24c12009-10-30 11:49:00 +00002096 statement->set_escaping_targets(collector.targets());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002097 try_block = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002098 try_block->AddStatement(statement);
2099 catch_block = NULL;
2100 }
2101
2102 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002103 if (catch_block != NULL) {
2104 ASSERT(finally_block == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002105 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
2106 result = new TryCatchStatement(try_block, catch_var_defn, catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002107 result->set_escaping_targets(collector.targets());
2108 } else {
2109 ASSERT(finally_block != NULL);
2110 result = new TryFinallyStatement(try_block, finally_block);
2111 // Add the jump targets of the try block and the catch block.
2112 for (int i = 0; i < collector.targets()->length(); i++) {
2113 catch_collector.AddTarget(collector.targets()->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002114 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002115 result->set_escaping_targets(catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002116 }
2117
2118 return result;
2119}
2120
2121
Steve Block3ce2e202009-11-05 08:53:23 +00002122DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2123 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002124 // DoStatement ::
2125 // 'do' Statement 'while' '(' Expression ')' ';'
2126
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002127 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002128 DoWhileStatement* loop = new DoWhileStatement(labels);
2129 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002130
2131 Expect(Token::DO, CHECK_OK);
2132 Statement* body = ParseStatement(NULL, CHECK_OK);
2133 Expect(Token::WHILE, CHECK_OK);
2134 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002135
2136 if (loop != NULL) {
2137 int position = scanner().location().beg_pos;
2138 loop->set_condition_position(position);
2139 }
2140
Steve Blocka7e24c12009-10-30 11:49:00 +00002141 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002142 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002143 Expect(Token::RPAREN, CHECK_OK);
2144
2145 // Allow do-statements to be terminated with and without
2146 // semi-colons. This allows code such as 'do;while(0)return' to
2147 // parse, which would not be the case if we had used the
2148 // ExpectSemicolon() functionality here.
2149 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2150
Steve Block3ce2e202009-11-05 08:53:23 +00002151 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002152 return loop;
2153}
2154
2155
Steve Block3ce2e202009-11-05 08:53:23 +00002156WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002157 // WhileStatement ::
2158 // 'while' '(' Expression ')' Statement
2159
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002160 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002161 WhileStatement* loop = new WhileStatement(labels);
2162 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002163
2164 Expect(Token::WHILE, CHECK_OK);
2165 Expect(Token::LPAREN, CHECK_OK);
2166 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002167 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002168 Expect(Token::RPAREN, CHECK_OK);
2169 Statement* body = ParseStatement(NULL, CHECK_OK);
2170
Steve Block3ce2e202009-11-05 08:53:23 +00002171 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002172 return loop;
2173}
2174
2175
2176Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2177 // ForStatement ::
2178 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2179
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002180 temp_scope_->AddLoop();
Steve Blocka7e24c12009-10-30 11:49:00 +00002181 Statement* init = NULL;
2182
2183 Expect(Token::FOR, CHECK_OK);
2184 Expect(Token::LPAREN, CHECK_OK);
2185 if (peek() != Token::SEMICOLON) {
2186 if (peek() == Token::VAR || peek() == Token::CONST) {
2187 Expression* each = NULL;
2188 Block* variable_statement =
2189 ParseVariableDeclarations(false, &each, CHECK_OK);
2190 if (peek() == Token::IN && each != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002191 ForInStatement* loop = new ForInStatement(labels);
2192 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002193
2194 Expect(Token::IN, CHECK_OK);
2195 Expression* enumerable = ParseExpression(true, CHECK_OK);
2196 Expect(Token::RPAREN, CHECK_OK);
2197
2198 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002199 loop->Initialize(each, enumerable, body);
2200 Block* result = new Block(NULL, 2, false);
2201 result->AddStatement(variable_statement);
2202 result->AddStatement(loop);
2203 // Parsed for-in loop w/ variable/const declaration.
2204 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002205 } else {
2206 init = variable_statement;
2207 }
2208
2209 } else {
2210 Expression* expression = ParseExpression(false, CHECK_OK);
2211 if (peek() == Token::IN) {
2212 // Signal a reference error if the expression is an invalid
2213 // left-hand side expression. We could report this as a syntax
2214 // error here but for compatibility with JSC we choose to report
2215 // the error at runtime.
2216 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2217 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
2218 expression = NewThrowReferenceError(type);
2219 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002220 ForInStatement* loop = new ForInStatement(labels);
2221 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002222
2223 Expect(Token::IN, CHECK_OK);
2224 Expression* enumerable = ParseExpression(true, CHECK_OK);
2225 Expect(Token::RPAREN, CHECK_OK);
2226
2227 Statement* body = ParseStatement(NULL, CHECK_OK);
2228 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002229 // Parsed for-in loop.
2230 return loop;
2231
2232 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002233 init = new ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002234 }
2235 }
2236 }
2237
2238 // Standard 'for' loop
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002239 ForStatement* loop = new ForStatement(labels);
2240 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002241
2242 // Parsed initializer at this point.
2243 Expect(Token::SEMICOLON, CHECK_OK);
2244
2245 Expression* cond = NULL;
2246 if (peek() != Token::SEMICOLON) {
2247 cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002248 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002249 }
2250 Expect(Token::SEMICOLON, CHECK_OK);
2251
2252 Statement* next = NULL;
2253 if (peek() != Token::RPAREN) {
2254 Expression* exp = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002255 next = new ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002256 }
2257 Expect(Token::RPAREN, CHECK_OK);
2258
2259 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002260 if (loop) loop->Initialize(init, cond, next, body);
2261 return loop;
2262}
2263
2264
2265// Precedence = 1
2266Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2267 // Expression ::
2268 // AssignmentExpression
2269 // Expression ',' AssignmentExpression
2270
2271 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2272 while (peek() == Token::COMMA) {
2273 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002274 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002275 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002276 result = new BinaryOperation(Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002277 }
2278 return result;
2279}
2280
2281
2282// Precedence = 2
2283Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2284 // AssignmentExpression ::
2285 // ConditionalExpression
2286 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2287
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002288 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002289 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2290
2291 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002292 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002293 // Parsed conditional expression only (no assignment).
2294 return expression;
2295 }
2296
2297 // Signal a reference error if the expression is an invalid left-hand
2298 // side expression. We could report this as a syntax error here but
2299 // for compatibility with JSC we choose to report the error at
2300 // runtime.
2301 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2302 Handle<String> type = Factory::invalid_lhs_in_assignment_symbol();
2303 expression = NewThrowReferenceError(type);
2304 }
2305
Steve Block1e0659c2011-05-24 12:43:12 +01002306 if (temp_scope_->StrictMode()) {
2307 // Assignment to eval or arguments is disallowed in strict mode.
2308 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2309 }
2310
Steve Blocka7e24c12009-10-30 11:49:00 +00002311 Token::Value op = Next(); // Get assignment operator.
2312 int pos = scanner().location().beg_pos;
2313 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2314
2315 // TODO(1231235): We try to estimate the set of properties set by
2316 // constructors. We define a new property whenever there is an
2317 // assignment to a property of 'this'. We should probably only add
2318 // properties if we haven't seen them before. Otherwise we'll
2319 // probably overestimate the number of properties.
2320 Property* property = expression ? expression->AsProperty() : NULL;
2321 if (op == Token::ASSIGN &&
2322 property != NULL &&
2323 property->obj()->AsVariableProxy() != NULL &&
2324 property->obj()->AsVariableProxy()->is_this()) {
2325 temp_scope_->AddProperty();
2326 }
2327
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002328 // If we assign a function literal to a property we pretenure the
2329 // literal so it can be added as a constant function property.
2330 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2331 right->AsFunctionLiteral()->set_pretenure(true);
2332 }
2333
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002334 if (fni_ != NULL) {
2335 // Check if the right hand side is a call to avoid inferring a
2336 // name if we're dealing with "a = function(){...}();"-like
2337 // expression.
2338 if ((op == Token::INIT_VAR
2339 || op == Token::INIT_CONST
2340 || op == Token::ASSIGN)
2341 && (right->AsCall() == NULL)) {
2342 fni_->Infer();
2343 }
2344 fni_->Leave();
2345 }
2346
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002347 return new Assignment(op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002348}
2349
2350
2351// Precedence = 3
2352Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2353 // ConditionalExpression ::
2354 // LogicalOrExpression
2355 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2356
2357 // We start using the binary expression parser for prec >= 4 only!
2358 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2359 if (peek() != Token::CONDITIONAL) return expression;
2360 Consume(Token::CONDITIONAL);
2361 // In parsing the first assignment expression in conditional
2362 // expressions we always accept the 'in' keyword; see ECMA-262,
2363 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002364 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002365 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2366 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002367 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002368 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002369 return new Conditional(expression, left, right,
2370 left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002371}
2372
2373
2374static int Precedence(Token::Value tok, bool accept_IN) {
2375 if (tok == Token::IN && !accept_IN)
2376 return 0; // 0 precedence will terminate binary expression parsing
2377
2378 return Token::Precedence(tok);
2379}
2380
2381
2382// Precedence >= 4
2383Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2384 ASSERT(prec >= 4);
2385 Expression* x = ParseUnaryExpression(CHECK_OK);
2386 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2387 // prec1 >= 4
2388 while (Precedence(peek(), accept_IN) == prec1) {
2389 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002390 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002391 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2392
2393 // Compute some expressions involving only number literals.
2394 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2395 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2396 double x_val = x->AsLiteral()->handle()->Number();
2397 double y_val = y->AsLiteral()->handle()->Number();
2398
2399 switch (op) {
2400 case Token::ADD:
2401 x = NewNumberLiteral(x_val + y_val);
2402 continue;
2403 case Token::SUB:
2404 x = NewNumberLiteral(x_val - y_val);
2405 continue;
2406 case Token::MUL:
2407 x = NewNumberLiteral(x_val * y_val);
2408 continue;
2409 case Token::DIV:
2410 x = NewNumberLiteral(x_val / y_val);
2411 continue;
2412 case Token::BIT_OR:
2413 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2414 continue;
2415 case Token::BIT_AND:
2416 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2417 continue;
2418 case Token::BIT_XOR:
2419 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2420 continue;
2421 case Token::SHL: {
2422 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2423 x = NewNumberLiteral(value);
2424 continue;
2425 }
2426 case Token::SHR: {
2427 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2428 uint32_t value = DoubleToUint32(x_val) >> shift;
2429 x = NewNumberLiteral(value);
2430 continue;
2431 }
2432 case Token::SAR: {
2433 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2434 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2435 x = NewNumberLiteral(value);
2436 continue;
2437 }
2438 default:
2439 break;
2440 }
2441 }
2442
Steve Blocka7e24c12009-10-30 11:49:00 +00002443 // For now we distinguish between comparisons and other binary
2444 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002445 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002446 if (Token::IsCompareOp(op)) {
2447 // We have a comparison.
2448 Token::Value cmp = op;
2449 switch (op) {
2450 case Token::NE: cmp = Token::EQ; break;
2451 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2452 default: break;
2453 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002454 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002455 if (cmp != op) {
2456 // The comparison was negated - add a NOT.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002457 x = new UnaryOperation(Token::NOT, x);
Steve Blocka7e24c12009-10-30 11:49:00 +00002458 }
2459
2460 } else {
2461 // We have a "normal" binary operation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002462 x = new BinaryOperation(op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002463 }
2464 }
2465 }
2466 return x;
2467}
2468
2469
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002470Expression* Parser::NewCompareNode(Token::Value op,
2471 Expression* x,
2472 Expression* y,
2473 int position) {
2474 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002475 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002476 bool is_strict = (op == Token::EQ_STRICT);
2477 Literal* x_literal = x->AsLiteral();
2478 if (x_literal != NULL && x_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002479 return new CompareToNull(is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002480 }
2481
2482 Literal* y_literal = y->AsLiteral();
2483 if (y_literal != NULL && y_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002484 return new CompareToNull(is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002485 }
2486 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002487 return new CompareOperation(op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002488}
2489
2490
Steve Blocka7e24c12009-10-30 11:49:00 +00002491Expression* Parser::ParseUnaryExpression(bool* ok) {
2492 // UnaryExpression ::
2493 // PostfixExpression
2494 // 'delete' UnaryExpression
2495 // 'void' UnaryExpression
2496 // 'typeof' UnaryExpression
2497 // '++' UnaryExpression
2498 // '--' UnaryExpression
2499 // '+' UnaryExpression
2500 // '-' UnaryExpression
2501 // '~' UnaryExpression
2502 // '!' UnaryExpression
2503
2504 Token::Value op = peek();
2505 if (Token::IsUnaryOp(op)) {
2506 op = Next();
2507 Expression* expression = ParseUnaryExpression(CHECK_OK);
2508
2509 // Compute some expressions involving only number literals.
2510 if (expression != NULL && expression->AsLiteral() &&
2511 expression->AsLiteral()->handle()->IsNumber()) {
2512 double value = expression->AsLiteral()->handle()->Number();
2513 switch (op) {
2514 case Token::ADD:
2515 return expression;
2516 case Token::SUB:
2517 return NewNumberLiteral(-value);
2518 case Token::BIT_NOT:
2519 return NewNumberLiteral(~DoubleToInt32(value));
2520 default: break;
2521 }
2522 }
2523
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002524 return new UnaryOperation(op, expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002525
2526 } else if (Token::IsCountOp(op)) {
2527 op = Next();
2528 Expression* expression = ParseUnaryExpression(CHECK_OK);
2529 // Signal a reference error if the expression is an invalid
2530 // left-hand side expression. We could report this as a syntax
2531 // error here but for compatibility with JSC we choose to report the
2532 // error at runtime.
2533 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2534 Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
2535 expression = NewThrowReferenceError(type);
2536 }
Steve Block1e0659c2011-05-24 12:43:12 +01002537
2538 if (temp_scope_->StrictMode()) {
2539 // Prefix expression operand in strict mode may not be eval or arguments.
2540 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2541 }
2542
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002543 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002544 IncrementOperation* increment = new IncrementOperation(op, expression);
2545 return new CountOperation(true /* prefix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002546
2547 } else {
2548 return ParsePostfixExpression(ok);
2549 }
2550}
2551
2552
2553Expression* Parser::ParsePostfixExpression(bool* ok) {
2554 // PostfixExpression ::
2555 // LeftHandSideExpression ('++' | '--')?
2556
2557 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002558 if (!scanner().has_line_terminator_before_next() &&
2559 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002560 // Signal a reference error if the expression is an invalid
2561 // left-hand side expression. We could report this as a syntax
2562 // error here but for compatibility with JSC we choose to report the
2563 // error at runtime.
2564 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2565 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
2566 expression = NewThrowReferenceError(type);
2567 }
Steve Block1e0659c2011-05-24 12:43:12 +01002568
2569 if (temp_scope_->StrictMode()) {
2570 // Postfix expression operand in strict mode may not be eval or arguments.
2571 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2572 }
2573
Steve Blocka7e24c12009-10-30 11:49:00 +00002574 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002575 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002576 IncrementOperation* increment = new IncrementOperation(next, expression);
2577 expression = new CountOperation(false /* postfix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002578 }
2579 return expression;
2580}
2581
2582
2583Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2584 // LeftHandSideExpression ::
2585 // (NewExpression | MemberExpression) ...
2586
2587 Expression* result;
2588 if (peek() == Token::NEW) {
2589 result = ParseNewExpression(CHECK_OK);
2590 } else {
2591 result = ParseMemberExpression(CHECK_OK);
2592 }
2593
2594 while (true) {
2595 switch (peek()) {
2596 case Token::LBRACK: {
2597 Consume(Token::LBRACK);
2598 int pos = scanner().location().beg_pos;
2599 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002600 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002601 Expect(Token::RBRACK, CHECK_OK);
2602 break;
2603 }
2604
2605 case Token::LPAREN: {
2606 int pos = scanner().location().beg_pos;
2607 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2608
2609 // Keep track of eval() calls since they disable all local variable
2610 // optimizations.
2611 // The calls that need special treatment are the
2612 // direct (i.e. not aliased) eval calls. These calls are all of the
2613 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002614 // declared in the current scope chain.
2615 // These calls are marked as potentially direct eval calls. Whether
2616 // they are actually direct calls to eval is determined at run time.
2617 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2618 // in the local scope chain. It only matters that it's called "eval",
2619 // is called without a receiver and it refers to the original eval
2620 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002621 VariableProxy* callee = result->AsVariableProxy();
2622 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
2623 Handle<String> name = callee->name();
2624 Variable* var = top_scope_->Lookup(name);
2625 if (var == NULL) {
2626 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002627 }
2628 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002629 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002630 break;
2631 }
2632
2633 case Token::PERIOD: {
2634 Consume(Token::PERIOD);
2635 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002636 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002637 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002638 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002639 break;
2640 }
2641
2642 default:
2643 return result;
2644 }
2645 }
2646}
2647
2648
Steve Blocka7e24c12009-10-30 11:49:00 +00002649Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2650 // NewExpression ::
2651 // ('new')+ MemberExpression
2652
2653 // The grammar for new expressions is pretty warped. The keyword
2654 // 'new' can either be a part of the new expression (where it isn't
2655 // followed by an argument list) or a part of the member expression,
2656 // where it must be followed by an argument list. To accommodate
2657 // this, we parse the 'new' keywords greedily and keep track of how
2658 // many we have parsed. This information is then passed on to the
2659 // member expression parser, which is only allowed to match argument
2660 // lists as long as it has 'new' prefixes left
2661 Expect(Token::NEW, CHECK_OK);
2662 PositionStack::Element pos(stack, scanner().location().beg_pos);
2663
2664 Expression* result;
2665 if (peek() == Token::NEW) {
2666 result = ParseNewPrefix(stack, CHECK_OK);
2667 } else {
2668 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2669 }
2670
2671 if (!stack->is_empty()) {
2672 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002673 result = new CallNew(result, new ZoneList<Expression*>(0), last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002674 }
2675 return result;
2676}
2677
2678
2679Expression* Parser::ParseNewExpression(bool* ok) {
2680 PositionStack stack(ok);
2681 return ParseNewPrefix(&stack, ok);
2682}
2683
2684
2685Expression* Parser::ParseMemberExpression(bool* ok) {
2686 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2687}
2688
2689
2690Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2691 bool* ok) {
2692 // MemberExpression ::
2693 // (PrimaryExpression | FunctionLiteral)
2694 // ('[' Expression ']' | '.' Identifier | Arguments)*
2695
2696 // Parse the initial primary or function expression.
2697 Expression* result = NULL;
2698 if (peek() == Token::FUNCTION) {
2699 Expect(Token::FUNCTION, CHECK_OK);
2700 int function_token_position = scanner().location().beg_pos;
2701 Handle<String> name;
Steve Block1e0659c2011-05-24 12:43:12 +01002702 bool is_reserved_name = false;
2703 if (peek_any_identifier()) {
2704 name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK);
2705 }
2706 result = ParseFunctionLiteral(name, is_reserved_name,
2707 function_token_position, NESTED, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002708 } else {
2709 result = ParsePrimaryExpression(CHECK_OK);
2710 }
2711
2712 while (true) {
2713 switch (peek()) {
2714 case Token::LBRACK: {
2715 Consume(Token::LBRACK);
2716 int pos = scanner().location().beg_pos;
2717 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002718 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002719 Expect(Token::RBRACK, CHECK_OK);
2720 break;
2721 }
2722 case Token::PERIOD: {
2723 Consume(Token::PERIOD);
2724 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002725 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002726 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002727 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002728 break;
2729 }
2730 case Token::LPAREN: {
2731 if ((stack == NULL) || stack->is_empty()) return result;
2732 // Consume one of the new prefixes (already parsed).
2733 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2734 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002735 result = new CallNew(result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002736 break;
2737 }
2738 default:
2739 return result;
2740 }
2741 }
2742}
2743
2744
2745DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2746 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2747 // contexts this is used as a statement which invokes the debugger as i a
2748 // break point is present.
2749 // DebuggerStatement ::
2750 // 'debugger' ';'
2751
2752 Expect(Token::DEBUGGER, CHECK_OK);
2753 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002754 return new DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002755}
2756
2757
2758void Parser::ReportUnexpectedToken(Token::Value token) {
2759 // We don't report stack overflows here, to avoid increasing the
2760 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002761 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002762 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002763 // Four of the tokens are treated specially
2764 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002765 case Token::EOS:
2766 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2767 case Token::NUMBER:
2768 return ReportMessage("unexpected_token_number",
2769 Vector<const char*>::empty());
2770 case Token::STRING:
2771 return ReportMessage("unexpected_token_string",
2772 Vector<const char*>::empty());
2773 case Token::IDENTIFIER:
2774 return ReportMessage("unexpected_token_identifier",
2775 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002776 case Token::FUTURE_RESERVED_WORD:
2777 return ReportMessage(temp_scope_->StrictMode() ?
2778 "unexpected_strict_reserved" :
2779 "unexpected_token_identifier",
2780 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002781 default:
2782 const char* name = Token::String(token);
2783 ASSERT(name != NULL);
2784 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002785 }
2786}
2787
2788
Leon Clarkeac952652010-07-15 11:15:24 +01002789void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2790 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2791 const char* element[1] = { *name_string };
2792 ReportMessage("invalid_preparser_data",
2793 Vector<const char*>(element, 1));
2794 *ok = false;
2795}
2796
2797
Steve Blocka7e24c12009-10-30 11:49:00 +00002798Expression* Parser::ParsePrimaryExpression(bool* ok) {
2799 // PrimaryExpression ::
2800 // 'this'
2801 // 'null'
2802 // 'true'
2803 // 'false'
2804 // Identifier
2805 // Number
2806 // String
2807 // ArrayLiteral
2808 // ObjectLiteral
2809 // RegExpLiteral
2810 // '(' Expression ')'
2811
2812 Expression* result = NULL;
2813 switch (peek()) {
2814 case Token::THIS: {
2815 Consume(Token::THIS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002816 VariableProxy* recv = top_scope_->receiver();
2817 result = recv;
Steve Blocka7e24c12009-10-30 11:49:00 +00002818 break;
2819 }
2820
2821 case Token::NULL_LITERAL:
2822 Consume(Token::NULL_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002823 result = new Literal(Factory::null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002824 break;
2825
2826 case Token::TRUE_LITERAL:
2827 Consume(Token::TRUE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002828 result = new Literal(Factory::true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002829 break;
2830
2831 case Token::FALSE_LITERAL:
2832 Consume(Token::FALSE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002833 result = new Literal(Factory::false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002834 break;
2835
Steve Block1e0659c2011-05-24 12:43:12 +01002836 case Token::IDENTIFIER:
2837 case Token::FUTURE_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00002838 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002839 if (fni_ != NULL) fni_->PushVariableName(name);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002840 result = top_scope_->NewUnresolved(name, inside_with());
Steve Blocka7e24c12009-10-30 11:49:00 +00002841 break;
2842 }
2843
2844 case Token::NUMBER: {
2845 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01002846 ASSERT(scanner().is_literal_ascii());
2847 double value = StringToDouble(scanner().literal_ascii_string(),
2848 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002849 result = NewNumberLiteral(value);
2850 break;
2851 }
2852
2853 case Token::STRING: {
2854 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01002855 Handle<String> symbol = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002856 result = new Literal(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002857 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002858 break;
2859 }
2860
2861 case Token::ASSIGN_DIV:
2862 result = ParseRegExpLiteral(true, CHECK_OK);
2863 break;
2864
2865 case Token::DIV:
2866 result = ParseRegExpLiteral(false, CHECK_OK);
2867 break;
2868
2869 case Token::LBRACK:
2870 result = ParseArrayLiteral(CHECK_OK);
2871 break;
2872
2873 case Token::LBRACE:
2874 result = ParseObjectLiteral(CHECK_OK);
2875 break;
2876
2877 case Token::LPAREN:
2878 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002879 // Heuristically try to detect immediately called functions before
2880 // seeing the call parentheses.
2881 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00002882 result = ParseExpression(true, CHECK_OK);
2883 Expect(Token::RPAREN, CHECK_OK);
2884 break;
2885
2886 case Token::MOD:
2887 if (allow_natives_syntax_ || extension_ != NULL) {
2888 result = ParseV8Intrinsic(CHECK_OK);
2889 break;
2890 }
2891 // If we're not allowing special syntax we fall-through to the
2892 // default case.
2893
2894 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01002895 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00002896 ReportUnexpectedToken(tok);
2897 *ok = false;
2898 return NULL;
2899 }
2900 }
2901
2902 return result;
2903}
2904
2905
Leon Clarke4515c472010-02-03 11:58:03 +00002906void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
2907 Handle<FixedArray> literals,
2908 bool* is_simple,
2909 int* depth) {
2910 // Fill in the literals.
2911 // Accumulate output values in local variables.
2912 bool is_simple_acc = true;
2913 int depth_acc = 1;
2914 for (int i = 0; i < values->length(); i++) {
2915 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
2916 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2917 depth_acc = m_literal->depth() + 1;
2918 }
2919 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
2920 if (boilerplate_value->IsUndefined()) {
2921 literals->set_the_hole(i);
2922 is_simple_acc = false;
2923 } else {
2924 literals->set(i, *boilerplate_value);
2925 }
2926 }
2927
2928 *is_simple = is_simple_acc;
2929 *depth = depth_acc;
2930}
2931
2932
Steve Blocka7e24c12009-10-30 11:49:00 +00002933Expression* Parser::ParseArrayLiteral(bool* ok) {
2934 // ArrayLiteral ::
2935 // '[' Expression? (',' Expression?)* ']'
2936
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002937 ZoneList<Expression*>* values = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002938 Expect(Token::LBRACK, CHECK_OK);
2939 while (peek() != Token::RBRACK) {
2940 Expression* elem;
2941 if (peek() == Token::COMMA) {
2942 elem = GetLiteralTheHole();
2943 } else {
2944 elem = ParseAssignmentExpression(true, CHECK_OK);
2945 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002946 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00002947 if (peek() != Token::RBRACK) {
2948 Expect(Token::COMMA, CHECK_OK);
2949 }
2950 }
2951 Expect(Token::RBRACK, CHECK_OK);
2952
2953 // Update the scope information before the pre-parsing bailout.
Steve Blocka7e24c12009-10-30 11:49:00 +00002954 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
2955
Steve Blocka7e24c12009-10-30 11:49:00 +00002956 // Allocate a fixed array with all the literals.
2957 Handle<FixedArray> literals =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002958 Factory::NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002959
2960 // Fill in the literals.
2961 bool is_simple = true;
2962 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002963 for (int i = 0, n = values->length(); i < n; i++) {
2964 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00002965 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
2966 depth = m_literal->depth() + 1;
2967 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002968 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002969 if (boilerplate_value->IsUndefined()) {
2970 literals->set_the_hole(i);
2971 is_simple = false;
2972 } else {
2973 literals->set(i, *boilerplate_value);
2974 }
2975 }
2976
Iain Merrick75681382010-08-19 15:07:18 +01002977 // Simple and shallow arrays can be lazily copied, we transform the
2978 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002979 if (is_simple && depth == 1 && values->length() > 0) {
Iain Merrick75681382010-08-19 15:07:18 +01002980 literals->set_map(Heap::fixed_cow_array_map());
2981 }
2982
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002983 return new ArrayLiteral(literals, values,
2984 literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00002985}
2986
2987
2988bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
2989 return property != NULL &&
2990 property->kind() != ObjectLiteral::Property::PROTOTYPE;
2991}
2992
2993
2994bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002995 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002996 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
2997 return lit != NULL && lit->is_simple();
2998}
2999
Iain Merrick75681382010-08-19 15:07:18 +01003000
3001bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3002 Expression* value) {
3003 // If value is a literal the property value is already set in the
3004 // boilerplate object.
3005 if (value->AsLiteral() != NULL) return false;
3006 // If value is a materialized literal the property value is already set
3007 // in the boilerplate object if it is simple.
3008 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3009 return true;
3010}
3011
3012
Steve Blocka7e24c12009-10-30 11:49:00 +00003013Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3014 ASSERT(IsCompileTimeValue(expression));
3015 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
3016 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3017 if (object_literal != NULL) {
3018 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003019 if (object_literal->fast_elements()) {
3020 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3021 } else {
3022 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3023 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003024 result->set(kElementsSlot, *object_literal->constant_properties());
3025 } else {
3026 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3027 ASSERT(array_literal != NULL && array_literal->is_simple());
3028 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003029 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003030 }
3031 return result;
3032}
3033
3034
3035CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3036 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3037 return static_cast<Type>(type_value->value());
3038}
3039
3040
3041Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3042 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3043}
3044
3045
3046Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3047 if (expression->AsLiteral() != NULL) {
3048 return expression->AsLiteral()->handle();
3049 }
3050 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3051 return CompileTimeValue::GetValue(expression);
3052 }
3053 return Factory::undefined_value();
3054}
3055
Steve Block1e0659c2011-05-24 12:43:12 +01003056// Defined in ast.cc
3057bool IsEqualString(void* first, void* second);
3058bool IsEqualNumber(void* first, void* second);
3059
3060
3061// Validation per 11.1.5 Object Initialiser
3062class ObjectLiteralPropertyChecker {
3063 public:
3064 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3065 props(&IsEqualString),
3066 elems(&IsEqualNumber),
3067 parser_(parser),
3068 strict_(strict) {
3069 }
3070
3071 void CheckProperty(
3072 ObjectLiteral::Property* property,
3073 Scanner::Location loc,
3074 bool* ok);
3075
3076 private:
3077 enum PropertyKind {
3078 kGetAccessor = 0x01,
3079 kSetAccessor = 0x02,
3080 kAccessor = kGetAccessor | kSetAccessor,
3081 kData = 0x04
3082 };
3083
3084 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3085 switch (property->kind()) {
3086 case ObjectLiteral::Property::GETTER:
3087 return kGetAccessor;
3088 case ObjectLiteral::Property::SETTER:
3089 return kSetAccessor;
3090 default:
3091 return kData;
3092 }
3093 }
3094
3095 HashMap props;
3096 HashMap elems;
3097 Parser* parser_;
3098 bool strict_;
3099};
3100
3101
3102void ObjectLiteralPropertyChecker::CheckProperty(
3103 ObjectLiteral::Property* property,
3104 Scanner::Location loc,
3105 bool* ok) {
3106
3107 ASSERT(property != NULL);
3108
3109 Literal *lit = property->key();
3110 Handle<Object> handle = lit->handle();
3111
3112 uint32_t hash;
3113 HashMap* map;
3114 void* key;
3115
3116 if (handle->IsSymbol()) {
3117 Handle<String> name(String::cast(*handle));
3118 if (name->AsArrayIndex(&hash)) {
3119 Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
3120 key = key_handle.location();
3121 map = &elems;
3122 } else {
3123 key = handle.location();
3124 hash = name->Hash();
3125 map = &props;
3126 }
3127 } else if (handle->ToArrayIndex(&hash)) {
3128 key = handle.location();
3129 map = &elems;
3130 } else {
3131 ASSERT(handle->IsNumber());
3132 double num = handle->Number();
3133 char arr[100];
3134 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3135 const char* str = DoubleToCString(num, buffer);
3136 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
3137 key = name.location();
3138 hash = name->Hash();
3139 map = &props;
3140 }
3141
3142 // Lookup property previously defined, if any.
3143 HashMap::Entry* entry = map->Lookup(key, hash, true);
3144 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3145 intptr_t curr = GetPropertyKind(property);
3146
3147 // Duplicate data properties are illegal in strict mode.
3148 if (strict_ && (curr & prev & kData) != 0) {
3149 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3150 Vector<const char*>::empty());
3151 *ok = false;
3152 return;
3153 }
3154 // Data property conflicting with an accessor.
3155 if (((curr & kData) && (prev & kAccessor)) ||
3156 ((prev & kData) && (curr & kAccessor))) {
3157 parser_->ReportMessageAt(loc, "accessor_data_property",
3158 Vector<const char*>::empty());
3159 *ok = false;
3160 return;
3161 }
3162 // Two accessors of the same type conflicting
3163 if ((curr & prev & kAccessor) != 0) {
3164 parser_->ReportMessageAt(loc, "accessor_get_set",
3165 Vector<const char*>::empty());
3166 *ok = false;
3167 return;
3168 }
3169
3170 // Update map
3171 entry->value = reinterpret_cast<void*> (prev | curr);
3172 *ok = true;
3173}
3174
Steve Blocka7e24c12009-10-30 11:49:00 +00003175
Leon Clarke4515c472010-02-03 11:58:03 +00003176void Parser::BuildObjectLiteralConstantProperties(
3177 ZoneList<ObjectLiteral::Property*>* properties,
3178 Handle<FixedArray> constant_properties,
3179 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003180 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003181 int* depth) {
3182 int position = 0;
3183 // Accumulate the value in local variables and store it at the end.
3184 bool is_simple_acc = true;
3185 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003186 uint32_t max_element_index = 0;
3187 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003188 for (int i = 0; i < properties->length(); i++) {
3189 ObjectLiteral::Property* property = properties->at(i);
3190 if (!IsBoilerplateProperty(property)) {
3191 is_simple_acc = false;
3192 continue;
3193 }
3194 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3195 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3196 depth_acc = m_literal->depth() + 1;
3197 }
3198
3199 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3200 // value for COMPUTED properties, the real value is filled in at
3201 // runtime. The enumeration order is maintained.
3202 Handle<Object> key = property->key()->handle();
3203 Handle<Object> value = GetBoilerplateValue(property->value());
3204 is_simple_acc = is_simple_acc && !value->IsUndefined();
3205
Steve Block6ded16b2010-05-10 14:33:55 +01003206 // Keep track of the number of elements in the object literal and
3207 // the largest element index. If the largest element index is
3208 // much larger than the number of elements, creating an object
3209 // literal with fast elements will be a waste of space.
3210 uint32_t element_index = 0;
3211 if (key->IsString()
3212 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3213 && element_index > max_element_index) {
3214 max_element_index = element_index;
3215 elements++;
3216 } else if (key->IsSmi()) {
3217 int key_value = Smi::cast(*key)->value();
3218 if (key_value > 0
3219 && static_cast<uint32_t>(key_value) > max_element_index) {
3220 max_element_index = key_value;
3221 }
3222 elements++;
3223 }
3224
Leon Clarke4515c472010-02-03 11:58:03 +00003225 // Add name, value pair to the fixed array.
3226 constant_properties->set(position++, *key);
3227 constant_properties->set(position++, *value);
3228 }
Steve Block6ded16b2010-05-10 14:33:55 +01003229 *fast_elements =
3230 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003231 *is_simple = is_simple_acc;
3232 *depth = depth_acc;
3233}
3234
3235
Ben Murdochbb769b22010-08-11 14:56:33 +01003236ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3237 bool* ok) {
3238 // Special handling of getter and setter syntax:
3239 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3240 // We have already read the "get" or "set" keyword.
3241 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003242 bool is_keyword = Token::IsKeyword(next);
3243 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003244 next == Token::FUTURE_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003245 next == Token::STRING || is_keyword) {
3246 Handle<String> name;
3247 if (is_keyword) {
3248 name = Factory::LookupAsciiSymbol(Token::String(next));
3249 } else {
3250 name = GetSymbol(CHECK_OK);
3251 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003252 FunctionLiteral* value =
3253 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003254 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003255 RelocInfo::kNoPosition,
3256 DECLARATION,
3257 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003258 // Allow any number of parameters for compatiabilty with JSC.
3259 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003260 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003261 new ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003262 return property;
3263 } else {
3264 ReportUnexpectedToken(next);
3265 *ok = false;
3266 return NULL;
3267 }
3268}
3269
3270
Steve Blocka7e24c12009-10-30 11:49:00 +00003271Expression* Parser::ParseObjectLiteral(bool* ok) {
3272 // ObjectLiteral ::
3273 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003274 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3275 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003276 // )*[','] '}'
3277
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003278 ZoneList<ObjectLiteral::Property*>* properties =
3279 new ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003280 int number_of_boilerplate_properties = 0;
3281
Steve Block1e0659c2011-05-24 12:43:12 +01003282 ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode());
3283
Steve Blocka7e24c12009-10-30 11:49:00 +00003284 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003285 Scanner::Location loc = scanner().location();
3286
Steve Blocka7e24c12009-10-30 11:49:00 +00003287 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003288 if (fni_ != NULL) fni_->Enter();
3289
Steve Blocka7e24c12009-10-30 11:49:00 +00003290 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003291 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003292
3293 // Location of the property name token
3294 Scanner::Location loc = scanner().peek_location();
3295
Ben Murdochbb769b22010-08-11 14:56:33 +01003296 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003297 case Token::FUTURE_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003298 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003299 bool is_getter = false;
3300 bool is_setter = false;
3301 Handle<String> id =
3302 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003303 if (fni_ != NULL) fni_->PushLiteralName(id);
3304
Ben Murdochbb769b22010-08-11 14:56:33 +01003305 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003306 // Update loc to point to the identifier
3307 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003308 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003309 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3310 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003311 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003312 }
Steve Block1e0659c2011-05-24 12:43:12 +01003313 // Validate the property.
3314 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003315 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003316 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003317
3318 if (fni_ != NULL) {
3319 fni_->Infer();
3320 fni_->Leave();
3321 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003322 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003323 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003324 // Failed to parse as get/set property, so it's just a property
3325 // called "get" or "set".
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003326 key = new Literal(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003327 break;
3328 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003329 case Token::STRING: {
3330 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003331 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003332 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003333 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003334 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003335 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003336 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003337 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003338 key = new Literal(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003339 break;
3340 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003341 case Token::NUMBER: {
3342 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003343 ASSERT(scanner().is_literal_ascii());
3344 double value = StringToDouble(scanner().literal_ascii_string(),
3345 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003346 key = NewNumberLiteral(value);
3347 break;
3348 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003349 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003350 if (Token::IsKeyword(next)) {
3351 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003352 Handle<String> string = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003353 key = new Literal(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003354 } else {
3355 // Unexpected token.
3356 Token::Value next = Next();
3357 ReportUnexpectedToken(next);
3358 *ok = false;
3359 return NULL;
3360 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003361 }
3362
3363 Expect(Token::COLON, CHECK_OK);
3364 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3365
3366 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003367 new ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003368
3369 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3370 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003371 // Validate the property
3372 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003373 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003374
3375 // TODO(1240767): Consider allowing trailing comma.
3376 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003377
3378 if (fni_ != NULL) {
3379 fni_->Infer();
3380 fni_->Leave();
3381 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003382 }
3383 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003384
Steve Blocka7e24c12009-10-30 11:49:00 +00003385 // Computation of literal_index must happen before pre parse bailout.
3386 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003387
3388 Handle<FixedArray> constant_properties =
3389 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003390
Steve Blocka7e24c12009-10-30 11:49:00 +00003391 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003392 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003393 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003394 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003395 constant_properties,
3396 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003397 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003398 &depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003399 return new ObjectLiteral(constant_properties,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003400 properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003401 literal_index,
3402 is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003403 fast_elements,
Steve Blocka7e24c12009-10-30 11:49:00 +00003404 depth);
3405}
3406
3407
3408Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003409 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003410 Next();
3411 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3412 *ok = false;
3413 return NULL;
3414 }
3415
3416 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
3417
Steve Block9fac8402011-05-12 15:51:54 +01003418 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003419 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003420 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003421 Next();
3422
3423 return new RegExpLiteral(js_pattern, js_flags, literal_index);
3424}
3425
3426
3427ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3428 // Arguments ::
3429 // '(' (AssignmentExpression)*[','] ')'
3430
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003431 ZoneList<Expression*>* result = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003432 Expect(Token::LPAREN, CHECK_OK);
3433 bool done = (peek() == Token::RPAREN);
3434 while (!done) {
3435 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003436 result->Add(argument);
Steve Blocka7e24c12009-10-30 11:49:00 +00003437 done = (peek() == Token::RPAREN);
3438 if (!done) Expect(Token::COMMA, CHECK_OK);
3439 }
3440 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003441 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003442}
3443
3444
3445FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
Steve Block1e0659c2011-05-24 12:43:12 +01003446 bool name_is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003447 int function_token_position,
3448 FunctionLiteralType type,
3449 bool* ok) {
3450 // Function ::
3451 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003452 bool is_named = !var_name.is_null();
3453
3454 // The name associated with this function. If it's a function expression,
3455 // this is the actual function name, otherwise this is the name of the
3456 // variable declared and initialized with the function (expression). In
3457 // that case, we don't have a function name (it's empty).
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003458 Handle<String> name = is_named ? var_name : Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003459 // The function name, if any.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003460 Handle<String> function_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003461 if (is_named && (type == EXPRESSION || type == NESTED)) {
3462 function_name = name;
3463 }
3464
3465 int num_parameters = 0;
3466 // Parse function body.
Ben Murdochf87a2032010-10-22 12:50:53 +01003467 { Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003468 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3469 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
3470 scope);
3471 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003472 top_scope_->SetScopeName(name);
3473
3474 // FormalParameterList ::
3475 // '(' (Identifier)*[','] ')'
3476 Expect(Token::LPAREN, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003477 int start_pos = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01003478 Scanner::Location name_loc = Scanner::NoLocation();
3479 Scanner::Location dupe_loc = Scanner::NoLocation();
3480 Scanner::Location reserved_loc = Scanner::NoLocation();
3481
Steve Blocka7e24c12009-10-30 11:49:00 +00003482 bool done = (peek() == Token::RPAREN);
3483 while (!done) {
Steve Block1e0659c2011-05-24 12:43:12 +01003484 bool is_reserved = false;
3485 Handle<String> param_name =
3486 ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
3487
3488 // Store locations for possible future error reports.
3489 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3490 name_loc = scanner().location();
3491 }
3492 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
3493 dupe_loc = scanner().location();
3494 }
3495 if (!reserved_loc.IsValid() && is_reserved) {
3496 reserved_loc = scanner().location();
3497 }
3498
3499 Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR);
3500 top_scope_->AddParameter(parameter);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003501 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003502 if (num_parameters > kMaxNumFunctionParameters) {
3503 ReportMessageAt(scanner().location(), "too_many_parameters",
3504 Vector<const char*>::empty());
3505 *ok = false;
3506 return NULL;
3507 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003508 done = (peek() == Token::RPAREN);
3509 if (!done) Expect(Token::COMMA, CHECK_OK);
3510 }
3511 Expect(Token::RPAREN, CHECK_OK);
3512
3513 Expect(Token::LBRACE, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003514 ZoneList<Statement*>* body = new ZoneList<Statement*>(8);
Steve Blocka7e24c12009-10-30 11:49:00 +00003515
3516 // If we have a named function expression, we add a local variable
3517 // declaration to the body of the function with the name of the
3518 // function and let it refer to the function itself (closure).
3519 // NOTE: We create a proxy and resolve it here so that in the
3520 // future we can change the AST to only refer to VariableProxies
3521 // instead of Variables and Proxis as is the case now.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003522 if (!function_name.is_null() && function_name->length() > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003523 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3524 VariableProxy* fproxy =
3525 top_scope_->NewUnresolved(function_name, inside_with());
3526 fproxy->BindTo(fvar);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003527 body->Add(new ExpressionStatement(
3528 new Assignment(Token::INIT_CONST, fproxy,
3529 new ThisFunction(),
3530 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003531 }
3532
3533 // Determine if the function will be lazily compiled. The mode can
3534 // only be PARSE_LAZILY if the --lazy flag is true.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003535 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3536 top_scope_->outer_scope()->is_global_scope() &&
3537 top_scope_->HasTrivialOuterContext() &&
3538 !parenthesized_function_);
3539 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003540
Ben Murdochb0fe1622011-05-05 13:52:32 +01003541 int function_block_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003542 int materialized_literal_count;
3543 int expected_property_count;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003544 int end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003545 bool only_simple_this_property_assignments;
3546 Handle<FixedArray> this_property_assignments;
3547 if (is_lazily_compiled && pre_data() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003548 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003549 if (!entry.is_valid()) {
3550 ReportInvalidPreparseData(name, CHECK_OK);
3551 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003552 end_pos = entry.end_pos();
3553 if (end_pos <= function_block_pos) {
Leon Clarkeac952652010-07-15 11:15:24 +01003554 // End position greater than end of stream is safe, and hard to check.
3555 ReportInvalidPreparseData(name, CHECK_OK);
3556 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003557 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003558 // Seek to position just before terminal '}'.
3559 scanner().SeekForward(end_pos - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003560 materialized_literal_count = entry.literal_count();
3561 expected_property_count = entry.property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003562 only_simple_this_property_assignments = false;
3563 this_property_assignments = Factory::empty_fixed_array();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003564 Expect(Token::RBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003565 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003566 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3567
Steve Blocka7e24c12009-10-30 11:49:00 +00003568 materialized_literal_count = temp_scope.materialized_literal_count();
3569 expected_property_count = temp_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003570 only_simple_this_property_assignments =
3571 temp_scope.only_simple_this_property_assignments();
3572 this_property_assignments = temp_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003573
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003574 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003575 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003576 }
3577
Steve Block1e0659c2011-05-24 12:43:12 +01003578 // Validate strict mode.
3579 if (temp_scope_->StrictMode()) {
3580 if (IsEvalOrArguments(name)) {
3581 int position = function_token_position != RelocInfo::kNoPosition
3582 ? function_token_position
3583 : (start_pos > 0 ? start_pos - 1 : start_pos);
3584 Scanner::Location location = Scanner::Location(position, start_pos);
3585 ReportMessageAt(location,
3586 "strict_function_name", Vector<const char*>::empty());
3587 *ok = false;
3588 return NULL;
3589 }
3590 if (name_loc.IsValid()) {
3591 ReportMessageAt(name_loc, "strict_param_name",
3592 Vector<const char*>::empty());
3593 *ok = false;
3594 return NULL;
3595 }
3596 if (dupe_loc.IsValid()) {
3597 ReportMessageAt(dupe_loc, "strict_param_dupe",
3598 Vector<const char*>::empty());
3599 *ok = false;
3600 return NULL;
3601 }
3602 if (name_is_reserved) {
3603 int position = function_token_position != RelocInfo::kNoPosition
3604 ? function_token_position
3605 : (start_pos > 0 ? start_pos - 1 : start_pos);
3606 Scanner::Location location = Scanner::Location(position, start_pos);
3607 ReportMessageAt(location, "strict_reserved_word",
3608 Vector<const char*>::empty());
3609 *ok = false;
3610 return NULL;
3611 }
3612 if (reserved_loc.IsValid()) {
3613 ReportMessageAt(reserved_loc, "strict_reserved_word",
3614 Vector<const char*>::empty());
3615 *ok = false;
3616 return NULL;
3617 }
3618 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3619 }
3620
Steve Blocka7e24c12009-10-30 11:49:00 +00003621 FunctionLiteral* function_literal =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003622 new FunctionLiteral(name,
Steve Blocka7e24c12009-10-30 11:49:00 +00003623 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003624 body,
Steve Blocka7e24c12009-10-30 11:49:00 +00003625 materialized_literal_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003626 expected_property_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003627 only_simple_this_property_assignments,
3628 this_property_assignments,
3629 num_parameters,
3630 start_pos,
3631 end_pos,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003632 function_name->length() > 0,
Steve Block1e0659c2011-05-24 12:43:12 +01003633 temp_scope.ContainsLoops(),
3634 temp_scope.StrictMode());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003635 function_literal->set_function_token_position(function_token_position);
Steve Block6ded16b2010-05-10 14:33:55 +01003636
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003637 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
Steve Blocka7e24c12009-10-30 11:49:00 +00003638 return function_literal;
3639 }
3640}
3641
3642
3643Expression* Parser::ParseV8Intrinsic(bool* ok) {
3644 // CallRuntime ::
3645 // '%' Identifier Arguments
3646
3647 Expect(Token::MOD, CHECK_OK);
3648 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003649 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003650
3651 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003652 // The extension structures are only accessible while parsing the
3653 // very first time not when reparsing because of lazy compilation.
3654 top_scope_->ForceEagerCompilation();
3655 }
3656
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003657 Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003658
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003659 // Check for built-in IS_VAR macro.
3660 if (function != NULL &&
3661 function->intrinsic_type == Runtime::RUNTIME &&
3662 function->function_id == Runtime::kIS_VAR) {
3663 // %IS_VAR(x) evaluates to x if x is a variable,
3664 // leads to a parse error otherwise. Could be implemented as an
3665 // inline function %_IS_VAR(x) to eliminate this special case.
3666 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3667 return args->at(0);
3668 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003669 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003670 *ok = false;
3671 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003672 }
3673 }
3674
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003675 // Check that the expected number of arguments are being passed.
3676 if (function != NULL &&
3677 function->nargs != -1 &&
3678 function->nargs != args->length()) {
3679 ReportMessage("illegal_access", Vector<const char*>::empty());
3680 *ok = false;
3681 return NULL;
3682 }
3683
3684 // We have a valid intrinsics call or a call to a builtin.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003685 return new CallRuntime(name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003686}
3687
3688
Steve Block1e0659c2011-05-24 12:43:12 +01003689bool Parser::peek_any_identifier() {
3690 Token::Value next = peek();
3691 return next == Token::IDENTIFIER ||
3692 next == Token::FUTURE_RESERVED_WORD;
3693}
3694
3695
Steve Blocka7e24c12009-10-30 11:49:00 +00003696void Parser::Consume(Token::Value token) {
3697 Token::Value next = Next();
3698 USE(next);
3699 USE(token);
3700 ASSERT(next == token);
3701}
3702
3703
3704void Parser::Expect(Token::Value token, bool* ok) {
3705 Token::Value next = Next();
3706 if (next == token) return;
3707 ReportUnexpectedToken(next);
3708 *ok = false;
3709}
3710
3711
Leon Clarke4515c472010-02-03 11:58:03 +00003712bool Parser::Check(Token::Value token) {
3713 Token::Value next = peek();
3714 if (next == token) {
3715 Consume(next);
3716 return true;
3717 }
3718 return false;
3719}
3720
3721
Steve Blocka7e24c12009-10-30 11:49:00 +00003722void Parser::ExpectSemicolon(bool* ok) {
3723 // Check for automatic semicolon insertion according to
3724 // the rules given in ECMA-262, section 7.9, page 21.
3725 Token::Value tok = peek();
3726 if (tok == Token::SEMICOLON) {
3727 Next();
3728 return;
3729 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003730 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003731 tok == Token::RBRACE ||
3732 tok == Token::EOS) {
3733 return;
3734 }
3735 Expect(Token::SEMICOLON, ok);
3736}
3737
3738
3739Literal* Parser::GetLiteralUndefined() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003740 return new Literal(Factory::undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003741}
3742
3743
3744Literal* Parser::GetLiteralTheHole() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003745 return new Literal(Factory::the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003746}
3747
3748
3749Literal* Parser::GetLiteralNumber(double value) {
3750 return NewNumberLiteral(value);
3751}
3752
3753
3754Handle<String> Parser::ParseIdentifier(bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003755 bool is_reserved;
3756 return ParseIdentifierOrReservedWord(&is_reserved, ok);
3757}
3758
3759
3760Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved,
3761 bool* ok) {
3762 *is_reserved = false;
3763 if (temp_scope_->StrictMode()) {
3764 Expect(Token::IDENTIFIER, ok);
3765 } else {
3766 if (!Check(Token::IDENTIFIER)) {
3767 Expect(Token::FUTURE_RESERVED_WORD, ok);
3768 *is_reserved = true;
3769 }
3770 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003771 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003772 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003773}
3774
Ben Murdochbb769b22010-08-11 14:56:33 +01003775
3776Handle<String> Parser::ParseIdentifierName(bool* ok) {
3777 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01003778 if (next != Token::IDENTIFIER &&
3779 next != Token::FUTURE_RESERVED_WORD &&
3780 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01003781 ReportUnexpectedToken(next);
3782 *ok = false;
3783 return Handle<String>();
3784 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003785 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01003786}
3787
3788
Steve Block1e0659c2011-05-24 12:43:12 +01003789// Checks LHS expression for assignment and prefix/postfix increment/decrement
3790// in strict mode.
3791void Parser::CheckStrictModeLValue(Expression* expression,
3792 const char* error,
3793 bool* ok) {
3794 ASSERT(temp_scope_->StrictMode());
3795 VariableProxy* lhs = expression != NULL
3796 ? expression->AsVariableProxy()
3797 : NULL;
3798
3799 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
3800 ReportMessage(error, Vector<const char*>::empty());
3801 *ok = false;
3802 }
3803}
3804
3805
3806// Checks whether octal literal last seen is between beg_pos and end_pos.
3807// If so, reports an error.
3808void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
3809 int octal = scanner().octal_position();
3810 if (beg_pos <= octal && octal <= end_pos) {
3811 ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal",
3812 Vector<const char*>::empty());
3813 scanner().clear_octal_position();
3814 *ok = false;
3815 }
3816}
3817
3818
Steve Blocka7e24c12009-10-30 11:49:00 +00003819// This function reads an identifier and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01003820// is 'get' or 'set'.
Steve Blocka7e24c12009-10-30 11:49:00 +00003821Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3822 bool* is_set,
3823 bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003824 Handle<String> result = ParseIdentifier(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003825 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01003826 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
3827 const char* token = scanner().literal_ascii_string().start();
3828 *is_get = strncmp(token, "get", 3) == 0;
3829 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003830 }
Steve Block1e0659c2011-05-24 12:43:12 +01003831 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003832}
3833
3834
3835// ----------------------------------------------------------------------------
3836// Parser support
3837
3838
3839bool Parser::TargetStackContainsLabel(Handle<String> label) {
3840 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3841 BreakableStatement* stat = t->node()->AsBreakableStatement();
3842 if (stat != NULL && ContainsLabel(stat->labels(), label))
3843 return true;
3844 }
3845 return false;
3846}
3847
3848
3849BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3850 bool anonymous = label.is_null();
3851 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3852 BreakableStatement* stat = t->node()->AsBreakableStatement();
3853 if (stat == NULL) continue;
3854 if ((anonymous && stat->is_target_for_anonymous()) ||
3855 (!anonymous && ContainsLabel(stat->labels(), label))) {
3856 RegisterTargetUse(stat->break_target(), t->previous());
3857 return stat;
3858 }
3859 }
3860 return NULL;
3861}
3862
3863
3864IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3865 bool* ok) {
3866 bool anonymous = label.is_null();
3867 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3868 IterationStatement* stat = t->node()->AsIterationStatement();
3869 if (stat == NULL) continue;
3870
3871 ASSERT(stat->is_target_for_anonymous());
3872 if (anonymous || ContainsLabel(stat->labels(), label)) {
3873 RegisterTargetUse(stat->continue_target(), t->previous());
3874 return stat;
3875 }
3876 }
3877 return NULL;
3878}
3879
3880
3881void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) {
3882 // Register that a break target found at the given stop in the
3883 // target stack has been used from the top of the target stack. Add
3884 // the break target to any TargetCollectors passed on the stack.
3885 for (Target* t = target_stack_; t != stop; t = t->previous()) {
3886 TargetCollector* collector = t->node()->AsTargetCollector();
3887 if (collector != NULL) collector->AddTarget(target);
3888 }
3889}
3890
3891
3892Literal* Parser::NewNumberLiteral(double number) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003893 return new Literal(Factory::NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00003894}
3895
3896
3897Expression* Parser::NewThrowReferenceError(Handle<String> type) {
3898 return NewThrowError(Factory::MakeReferenceError_symbol(),
3899 type, HandleVector<Object>(NULL, 0));
3900}
3901
3902
3903Expression* Parser::NewThrowSyntaxError(Handle<String> type,
3904 Handle<Object> first) {
3905 int argc = first.is_null() ? 0 : 1;
3906 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
3907 return NewThrowError(Factory::MakeSyntaxError_symbol(), type, arguments);
3908}
3909
3910
3911Expression* Parser::NewThrowTypeError(Handle<String> type,
3912 Handle<Object> first,
3913 Handle<Object> second) {
3914 ASSERT(!first.is_null() && !second.is_null());
3915 Handle<Object> elements[] = { first, second };
3916 Vector< Handle<Object> > arguments =
3917 HandleVector<Object>(elements, ARRAY_SIZE(elements));
3918 return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments);
3919}
3920
3921
3922Expression* Parser::NewThrowError(Handle<String> constructor,
3923 Handle<String> type,
3924 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003925 int argc = arguments.length();
Steve Block1e0659c2011-05-24 12:43:12 +01003926 Handle<FixedArray> elements = Factory::NewFixedArray(argc, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003927 for (int i = 0; i < argc; i++) {
3928 Handle<Object> element = arguments[i];
3929 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003930 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00003931 }
3932 }
Steve Block1e0659c2011-05-24 12:43:12 +01003933 Handle<JSArray> array = Factory::NewJSArrayWithElements(elements, TENURED);
3934
Steve Blocka7e24c12009-10-30 11:49:00 +00003935 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
3936 args->Add(new Literal(type));
3937 args->Add(new Literal(array));
3938 return new Throw(new CallRuntime(constructor, NULL, args),
3939 scanner().location().beg_pos);
3940}
3941
Leon Clarke4515c472010-02-03 11:58:03 +00003942// ----------------------------------------------------------------------------
3943// JSON
3944
Ben Murdochb0fe1622011-05-05 13:52:32 +01003945Handle<Object> JsonParser::ParseJson(Handle<String> script,
3946 UC16CharacterStream* source) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08003947 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003948 stack_overflow_ = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003949 Handle<Object> result = ParseJsonValue();
3950 if (result.is_null() || scanner_.Next() != Token::EOS) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003951 if (stack_overflow_) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003952 // Scanner failed.
3953 Top::StackOverflow();
3954 } else {
3955 // Parse failed. Scanner's current token is the unexpected token.
3956 Token::Value token = scanner_.current_token();
3957
3958 const char* message;
3959 const char* name_opt = NULL;
3960
3961 switch (token) {
3962 case Token::EOS:
3963 message = "unexpected_eos";
3964 break;
3965 case Token::NUMBER:
3966 message = "unexpected_token_number";
3967 break;
3968 case Token::STRING:
3969 message = "unexpected_token_string";
3970 break;
3971 case Token::IDENTIFIER:
Steve Block1e0659c2011-05-24 12:43:12 +01003972 case Token::FUTURE_RESERVED_WORD:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003973 message = "unexpected_token_identifier";
3974 break;
3975 default:
3976 message = "unexpected_token";
3977 name_opt = Token::String(token);
3978 ASSERT(name_opt != NULL);
3979 break;
3980 }
3981
3982 Scanner::Location source_location = scanner_.location();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003983 MessageLocation location(Factory::NewScript(script),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003984 source_location.beg_pos,
3985 source_location.end_pos);
3986 int argc = (name_opt == NULL) ? 0 : 1;
3987 Handle<JSArray> array = Factory::NewJSArray(argc);
3988 if (name_opt != NULL) {
3989 SetElement(array,
3990 0,
3991 Factory::NewStringFromUtf8(CStrVector(name_opt)));
3992 }
3993 Handle<Object> result = Factory::NewSyntaxError(message, array);
3994 Top::Throw(*result, &location);
3995 return Handle<Object>::null();
3996 }
3997 }
Leon Clarke4515c472010-02-03 11:58:03 +00003998 return result;
3999}
4000
4001
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004002Handle<String> JsonParser::GetString() {
4003 int literal_length = scanner_.literal_length();
4004 if (literal_length == 0) {
4005 return Factory::empty_string();
4006 }
Steve Block9fac8402011-05-12 15:51:54 +01004007 if (scanner_.is_literal_ascii()) {
4008 return Factory::NewStringFromAscii(scanner_.literal_ascii_string());
4009 } else {
4010 return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string());
4011 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004012}
4013
4014
Leon Clarke4515c472010-02-03 11:58:03 +00004015// Parse any JSON value.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004016Handle<Object> JsonParser::ParseJsonValue() {
4017 Token::Value token = scanner_.Next();
Leon Clarke4515c472010-02-03 11:58:03 +00004018 switch (token) {
Steve Block1e0659c2011-05-24 12:43:12 +01004019 case Token::STRING:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004020 return GetString();
Steve Block1e0659c2011-05-24 12:43:12 +01004021 case Token::NUMBER:
4022 return Factory::NewNumber(scanner_.number());
Leon Clarke4515c472010-02-03 11:58:03 +00004023 case Token::FALSE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004024 return Factory::false_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004025 case Token::TRUE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004026 return Factory::true_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004027 case Token::NULL_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004028 return Factory::null_value();
4029 case Token::LBRACE:
4030 return ParseJsonObject();
4031 case Token::LBRACK:
4032 return ParseJsonArray();
Leon Clarke4515c472010-02-03 11:58:03 +00004033 default:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004034 return ReportUnexpectedToken();
Leon Clarke4515c472010-02-03 11:58:03 +00004035 }
4036}
4037
4038
4039// Parse a JSON object. Scanner must be right after '{' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004040Handle<Object> JsonParser::ParseJsonObject() {
4041 Handle<JSFunction> object_constructor(
4042 Top::global_context()->object_function());
4043 Handle<JSObject> json_object = Factory::NewJSObject(object_constructor);
4044 if (scanner_.peek() == Token::RBRACE) {
4045 scanner_.Next();
4046 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004047 if (StackLimitCheck().HasOverflowed()) {
4048 stack_overflow_ = true;
4049 return Handle<Object>::null();
4050 }
Leon Clarke4515c472010-02-03 11:58:03 +00004051 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004052 if (scanner_.Next() != Token::STRING) {
4053 return ReportUnexpectedToken();
4054 }
4055 Handle<String> key = GetString();
4056 if (scanner_.Next() != Token::COLON) {
4057 return ReportUnexpectedToken();
4058 }
4059 Handle<Object> value = ParseJsonValue();
4060 if (value.is_null()) return Handle<Object>::null();
Leon Clarke4515c472010-02-03 11:58:03 +00004061 uint32_t index;
4062 if (key->AsArrayIndex(&index)) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004063 SetOwnElement(json_object, index, value);
Steve Block1e0659c2011-05-24 12:43:12 +01004064 } else if (key->Equals(Heap::Proto_symbol())) {
4065 // We can't remove the __proto__ accessor since it's hardcoded
4066 // in several places. Instead go along and add the value as
4067 // the prototype of the created object if possible.
4068 SetPrototype(json_object, value);
Leon Clarke4515c472010-02-03 11:58:03 +00004069 } else {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004070 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
Leon Clarke4515c472010-02-03 11:58:03 +00004071 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004072 } while (scanner_.Next() == Token::COMMA);
4073 if (scanner_.current_token() != Token::RBRACE) {
4074 return ReportUnexpectedToken();
4075 }
Leon Clarke4515c472010-02-03 11:58:03 +00004076 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004077 return json_object;
Leon Clarke4515c472010-02-03 11:58:03 +00004078}
4079
4080
4081// Parse a JSON array. Scanner must be right after '[' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004082Handle<Object> JsonParser::ParseJsonArray() {
4083 ZoneScope zone_scope(DELETE_ON_EXIT);
4084 ZoneList<Handle<Object> > elements(4);
Leon Clarke4515c472010-02-03 11:58:03 +00004085
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004086 Token::Value token = scanner_.peek();
4087 if (token == Token::RBRACK) {
4088 scanner_.Next();
4089 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004090 if (StackLimitCheck().HasOverflowed()) {
4091 stack_overflow_ = true;
4092 return Handle<Object>::null();
4093 }
Leon Clarke4515c472010-02-03 11:58:03 +00004094 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004095 Handle<Object> element = ParseJsonValue();
4096 if (element.is_null()) return Handle<Object>::null();
4097 elements.Add(element);
4098 token = scanner_.Next();
4099 } while (token == Token::COMMA);
4100 if (token != Token::RBRACK) {
4101 return ReportUnexpectedToken();
4102 }
Leon Clarke4515c472010-02-03 11:58:03 +00004103 }
Leon Clarke4515c472010-02-03 11:58:03 +00004104
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004105 // Allocate a fixed array with all the elements.
4106 Handle<FixedArray> fast_elements =
4107 Factory::NewFixedArray(elements.length());
Leon Clarke4515c472010-02-03 11:58:03 +00004108
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004109 for (int i = 0, n = elements.length(); i < n; i++) {
4110 fast_elements->set(i, *elements[i]);
4111 }
Leon Clarke4515c472010-02-03 11:58:03 +00004112
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004113 return Factory::NewJSArrayWithElements(fast_elements);
Leon Clarke4515c472010-02-03 11:58:03 +00004114}
4115
Steve Blocka7e24c12009-10-30 11:49:00 +00004116// ----------------------------------------------------------------------------
4117// Regular expressions
4118
4119
4120RegExpParser::RegExpParser(FlatStringReader* in,
4121 Handle<String>* error,
4122 bool multiline)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004123 : error_(error),
4124 captures_(NULL),
4125 in_(in),
4126 current_(kEndMarker),
4127 next_pos_(0),
4128 capture_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +00004129 has_more_(true),
4130 multiline_(multiline),
Steve Blocka7e24c12009-10-30 11:49:00 +00004131 simple_(false),
4132 contains_anchor_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00004133 is_scanned_for_captures_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00004134 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004135 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004136}
4137
4138
4139uc32 RegExpParser::Next() {
4140 if (has_next()) {
4141 return in()->Get(next_pos_);
4142 } else {
4143 return kEndMarker;
4144 }
4145}
4146
4147
4148void RegExpParser::Advance() {
4149 if (next_pos_ < in()->length()) {
4150 StackLimitCheck check;
4151 if (check.HasOverflowed()) {
4152 ReportError(CStrVector(Top::kStackOverflowMessage));
4153 } else if (Zone::excess_allocation()) {
4154 ReportError(CStrVector("Regular expression too large"));
4155 } else {
4156 current_ = in()->Get(next_pos_);
4157 next_pos_++;
4158 }
4159 } else {
4160 current_ = kEndMarker;
4161 has_more_ = false;
4162 }
4163}
4164
4165
4166void RegExpParser::Reset(int pos) {
4167 next_pos_ = pos;
4168 Advance();
4169}
4170
4171
4172void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004173 next_pos_ += dist - 1;
4174 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004175}
4176
4177
4178bool RegExpParser::simple() {
4179 return simple_;
4180}
4181
4182RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4183 failed_ = true;
4184 *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
4185 // Zip to the end to make sure the no more input is read.
4186 current_ = kEndMarker;
4187 next_pos_ = in()->length();
4188 return NULL;
4189}
4190
4191
4192// Pattern ::
4193// Disjunction
4194RegExpTree* RegExpParser::ParsePattern() {
4195 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4196 ASSERT(!has_more());
4197 // If the result of parsing is a literal string atom, and it has the
4198 // same length as the input, then the atom is identical to the input.
4199 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4200 simple_ = true;
4201 }
4202 return result;
4203}
4204
4205
4206// Disjunction ::
4207// Alternative
4208// Alternative | Disjunction
4209// Alternative ::
4210// [empty]
4211// Term Alternative
4212// Term ::
4213// Assertion
4214// Atom
4215// Atom Quantifier
4216RegExpTree* RegExpParser::ParseDisjunction() {
4217 // Used to store current state while parsing subexpressions.
4218 RegExpParserState initial_state(NULL, INITIAL, 0);
4219 RegExpParserState* stored_state = &initial_state;
4220 // Cache the builder in a local variable for quick access.
4221 RegExpBuilder* builder = initial_state.builder();
4222 while (true) {
4223 switch (current()) {
4224 case kEndMarker:
4225 if (stored_state->IsSubexpression()) {
4226 // Inside a parenthesized group when hitting end of input.
4227 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4228 }
4229 ASSERT_EQ(INITIAL, stored_state->group_type());
4230 // Parsing completed successfully.
4231 return builder->ToRegExp();
4232 case ')': {
4233 if (!stored_state->IsSubexpression()) {
4234 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4235 }
4236 ASSERT_NE(INITIAL, stored_state->group_type());
4237
4238 Advance();
4239 // End disjunction parsing and convert builder content to new single
4240 // regexp atom.
4241 RegExpTree* body = builder->ToRegExp();
4242
4243 int end_capture_index = captures_started();
4244
4245 int capture_index = stored_state->capture_index();
4246 SubexpressionType type = stored_state->group_type();
4247
4248 // Restore previous state.
4249 stored_state = stored_state->previous_state();
4250 builder = stored_state->builder();
4251
4252 // Build result of subexpression.
4253 if (type == CAPTURE) {
4254 RegExpCapture* capture = new RegExpCapture(body, capture_index);
4255 captures_->at(capture_index - 1) = capture;
4256 body = capture;
4257 } else if (type != GROUPING) {
4258 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4259 bool is_positive = (type == POSITIVE_LOOKAHEAD);
4260 body = new RegExpLookahead(body,
4261 is_positive,
4262 end_capture_index - capture_index,
4263 capture_index);
4264 }
4265 builder->AddAtom(body);
4266 break;
4267 }
4268 case '|': {
4269 Advance();
4270 builder->NewAlternative();
4271 continue;
4272 }
4273 case '*':
4274 case '+':
4275 case '?':
4276 return ReportError(CStrVector("Nothing to repeat"));
4277 case '^': {
4278 Advance();
4279 if (multiline_) {
4280 builder->AddAssertion(
4281 new RegExpAssertion(RegExpAssertion::START_OF_LINE));
4282 } else {
4283 builder->AddAssertion(
4284 new RegExpAssertion(RegExpAssertion::START_OF_INPUT));
4285 set_contains_anchor();
4286 }
4287 continue;
4288 }
4289 case '$': {
4290 Advance();
4291 RegExpAssertion::Type type =
4292 multiline_ ? RegExpAssertion::END_OF_LINE :
4293 RegExpAssertion::END_OF_INPUT;
4294 builder->AddAssertion(new RegExpAssertion(type));
4295 continue;
4296 }
4297 case '.': {
4298 Advance();
4299 // everything except \x0a, \x0d, \u2028 and \u2029
4300 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4301 CharacterRange::AddClassEscape('.', ranges);
4302 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
4303 builder->AddAtom(atom);
4304 break;
4305 }
4306 case '(': {
4307 SubexpressionType type = CAPTURE;
4308 Advance();
4309 if (current() == '?') {
4310 switch (Next()) {
4311 case ':':
4312 type = GROUPING;
4313 break;
4314 case '=':
4315 type = POSITIVE_LOOKAHEAD;
4316 break;
4317 case '!':
4318 type = NEGATIVE_LOOKAHEAD;
4319 break;
4320 default:
4321 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4322 break;
4323 }
4324 Advance(2);
4325 } else {
4326 if (captures_ == NULL) {
4327 captures_ = new ZoneList<RegExpCapture*>(2);
4328 }
4329 if (captures_started() >= kMaxCaptures) {
4330 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4331 }
4332 captures_->Add(NULL);
4333 }
4334 // Store current state and begin new disjunction parsing.
4335 stored_state = new RegExpParserState(stored_state,
4336 type,
4337 captures_started());
4338 builder = stored_state->builder();
4339 break;
4340 }
4341 case '[': {
4342 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4343 builder->AddAtom(atom);
4344 break;
4345 }
4346 // Atom ::
4347 // \ AtomEscape
4348 case '\\':
4349 switch (Next()) {
4350 case kEndMarker:
4351 return ReportError(CStrVector("\\ at end of pattern"));
4352 case 'b':
4353 Advance(2);
4354 builder->AddAssertion(
4355 new RegExpAssertion(RegExpAssertion::BOUNDARY));
4356 continue;
4357 case 'B':
4358 Advance(2);
4359 builder->AddAssertion(
4360 new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
4361 continue;
4362 // AtomEscape ::
4363 // CharacterClassEscape
4364 //
4365 // CharacterClassEscape :: one of
4366 // d D s S w W
4367 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4368 uc32 c = Next();
4369 Advance(2);
4370 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4371 CharacterRange::AddClassEscape(c, ranges);
4372 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
4373 builder->AddAtom(atom);
4374 break;
4375 }
4376 case '1': case '2': case '3': case '4': case '5': case '6':
4377 case '7': case '8': case '9': {
4378 int index = 0;
4379 if (ParseBackReferenceIndex(&index)) {
4380 RegExpCapture* capture = NULL;
4381 if (captures_ != NULL && index <= captures_->length()) {
4382 capture = captures_->at(index - 1);
4383 }
4384 if (capture == NULL) {
4385 builder->AddEmpty();
4386 break;
4387 }
4388 RegExpTree* atom = new RegExpBackReference(capture);
4389 builder->AddAtom(atom);
4390 break;
4391 }
4392 uc32 first_digit = Next();
4393 if (first_digit == '8' || first_digit == '9') {
4394 // Treat as identity escape
4395 builder->AddCharacter(first_digit);
4396 Advance(2);
4397 break;
4398 }
4399 }
4400 // FALLTHROUGH
4401 case '0': {
4402 Advance();
4403 uc32 octal = ParseOctalLiteral();
4404 builder->AddCharacter(octal);
4405 break;
4406 }
4407 // ControlEscape :: one of
4408 // f n r t v
4409 case 'f':
4410 Advance(2);
4411 builder->AddCharacter('\f');
4412 break;
4413 case 'n':
4414 Advance(2);
4415 builder->AddCharacter('\n');
4416 break;
4417 case 'r':
4418 Advance(2);
4419 builder->AddCharacter('\r');
4420 break;
4421 case 't':
4422 Advance(2);
4423 builder->AddCharacter('\t');
4424 break;
4425 case 'v':
4426 Advance(2);
4427 builder->AddCharacter('\v');
4428 break;
4429 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004430 Advance();
4431 uc32 controlLetter = Next();
4432 // Special case if it is an ASCII letter.
4433 // Convert lower case letters to uppercase.
4434 uc32 letter = controlLetter & ~('a' ^ 'A');
4435 if (letter < 'A' || 'Z' < letter) {
4436 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4437 // This is outside the specification. We match JSC in
4438 // reading the backslash as a literal character instead
4439 // of as starting an escape.
4440 builder->AddCharacter('\\');
4441 } else {
4442 Advance(2);
4443 builder->AddCharacter(controlLetter & 0x1f);
4444 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004445 break;
4446 }
4447 case 'x': {
4448 Advance(2);
4449 uc32 value;
4450 if (ParseHexEscape(2, &value)) {
4451 builder->AddCharacter(value);
4452 } else {
4453 builder->AddCharacter('x');
4454 }
4455 break;
4456 }
4457 case 'u': {
4458 Advance(2);
4459 uc32 value;
4460 if (ParseHexEscape(4, &value)) {
4461 builder->AddCharacter(value);
4462 } else {
4463 builder->AddCharacter('u');
4464 }
4465 break;
4466 }
4467 default:
4468 // Identity escape.
4469 builder->AddCharacter(Next());
4470 Advance(2);
4471 break;
4472 }
4473 break;
4474 case '{': {
4475 int dummy;
4476 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4477 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4478 }
4479 // fallthrough
4480 }
4481 default:
4482 builder->AddCharacter(current());
4483 Advance();
4484 break;
4485 } // end switch(current())
4486
4487 int min;
4488 int max;
4489 switch (current()) {
4490 // QuantifierPrefix ::
4491 // *
4492 // +
4493 // ?
4494 // {
4495 case '*':
4496 min = 0;
4497 max = RegExpTree::kInfinity;
4498 Advance();
4499 break;
4500 case '+':
4501 min = 1;
4502 max = RegExpTree::kInfinity;
4503 Advance();
4504 break;
4505 case '?':
4506 min = 0;
4507 max = 1;
4508 Advance();
4509 break;
4510 case '{':
4511 if (ParseIntervalQuantifier(&min, &max)) {
4512 if (max < min) {
4513 ReportError(CStrVector("numbers out of order in {} quantifier.")
4514 CHECK_FAILED);
4515 }
4516 break;
4517 } else {
4518 continue;
4519 }
4520 default:
4521 continue;
4522 }
Leon Clarkee46be812010-01-19 14:06:41 +00004523 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004524 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004525 type = RegExpQuantifier::NON_GREEDY;
4526 Advance();
4527 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4528 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4529 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004530 Advance();
4531 }
Leon Clarkee46be812010-01-19 14:06:41 +00004532 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004533 }
4534}
4535
4536class SourceCharacter {
4537 public:
4538 static bool Is(uc32 c) {
4539 switch (c) {
4540 // case ']': case '}':
4541 // In spidermonkey and jsc these are treated as source characters
4542 // so we do too.
4543 case '^': case '$': case '\\': case '.': case '*': case '+':
4544 case '?': case '(': case ')': case '[': case '{': case '|':
4545 case RegExpParser::kEndMarker:
4546 return false;
4547 default:
4548 return true;
4549 }
4550 }
4551};
4552
4553
4554static unibrow::Predicate<SourceCharacter> source_character;
4555
4556
4557static inline bool IsSourceCharacter(uc32 c) {
4558 return source_character.get(c);
4559}
4560
4561#ifdef DEBUG
4562// Currently only used in an ASSERT.
4563static bool IsSpecialClassEscape(uc32 c) {
4564 switch (c) {
4565 case 'd': case 'D':
4566 case 's': case 'S':
4567 case 'w': case 'W':
4568 return true;
4569 default:
4570 return false;
4571 }
4572}
4573#endif
4574
4575
4576// In order to know whether an escape is a backreference or not we have to scan
4577// the entire regexp and find the number of capturing parentheses. However we
4578// don't want to scan the regexp twice unless it is necessary. This mini-parser
4579// is called when needed. It can see the difference between capturing and
4580// noncapturing parentheses and can skip character classes and backslash-escaped
4581// characters.
4582void RegExpParser::ScanForCaptures() {
4583 // Start with captures started previous to current position
4584 int capture_count = captures_started();
4585 // Add count of captures after this position.
4586 int n;
4587 while ((n = current()) != kEndMarker) {
4588 Advance();
4589 switch (n) {
4590 case '\\':
4591 Advance();
4592 break;
4593 case '[': {
4594 int c;
4595 while ((c = current()) != kEndMarker) {
4596 Advance();
4597 if (c == '\\') {
4598 Advance();
4599 } else {
4600 if (c == ']') break;
4601 }
4602 }
4603 break;
4604 }
4605 case '(':
4606 if (current() != '?') capture_count++;
4607 break;
4608 }
4609 }
4610 capture_count_ = capture_count;
4611 is_scanned_for_captures_ = true;
4612}
4613
4614
4615bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4616 ASSERT_EQ('\\', current());
4617 ASSERT('1' <= Next() && Next() <= '9');
4618 // Try to parse a decimal literal that is no greater than the total number
4619 // of left capturing parentheses in the input.
4620 int start = position();
4621 int value = Next() - '0';
4622 Advance(2);
4623 while (true) {
4624 uc32 c = current();
4625 if (IsDecimalDigit(c)) {
4626 value = 10 * value + (c - '0');
4627 if (value > kMaxCaptures) {
4628 Reset(start);
4629 return false;
4630 }
4631 Advance();
4632 } else {
4633 break;
4634 }
4635 }
4636 if (value > captures_started()) {
4637 if (!is_scanned_for_captures_) {
4638 int saved_position = position();
4639 ScanForCaptures();
4640 Reset(saved_position);
4641 }
4642 if (value > capture_count_) {
4643 Reset(start);
4644 return false;
4645 }
4646 }
4647 *index_out = value;
4648 return true;
4649}
4650
4651
4652// QuantifierPrefix ::
4653// { DecimalDigits }
4654// { DecimalDigits , }
4655// { DecimalDigits , DecimalDigits }
4656//
4657// Returns true if parsing succeeds, and set the min_out and max_out
4658// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4659bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4660 ASSERT_EQ(current(), '{');
4661 int start = position();
4662 Advance();
4663 int min = 0;
4664 if (!IsDecimalDigit(current())) {
4665 Reset(start);
4666 return false;
4667 }
4668 while (IsDecimalDigit(current())) {
4669 int next = current() - '0';
4670 if (min > (RegExpTree::kInfinity - next) / 10) {
4671 // Overflow. Skip past remaining decimal digits and return -1.
4672 do {
4673 Advance();
4674 } while (IsDecimalDigit(current()));
4675 min = RegExpTree::kInfinity;
4676 break;
4677 }
4678 min = 10 * min + next;
4679 Advance();
4680 }
4681 int max = 0;
4682 if (current() == '}') {
4683 max = min;
4684 Advance();
4685 } else if (current() == ',') {
4686 Advance();
4687 if (current() == '}') {
4688 max = RegExpTree::kInfinity;
4689 Advance();
4690 } else {
4691 while (IsDecimalDigit(current())) {
4692 int next = current() - '0';
4693 if (max > (RegExpTree::kInfinity - next) / 10) {
4694 do {
4695 Advance();
4696 } while (IsDecimalDigit(current()));
4697 max = RegExpTree::kInfinity;
4698 break;
4699 }
4700 max = 10 * max + next;
4701 Advance();
4702 }
4703 if (current() != '}') {
4704 Reset(start);
4705 return false;
4706 }
4707 Advance();
4708 }
4709 } else {
4710 Reset(start);
4711 return false;
4712 }
4713 *min_out = min;
4714 *max_out = max;
4715 return true;
4716}
4717
4718
Steve Blocka7e24c12009-10-30 11:49:00 +00004719uc32 RegExpParser::ParseOctalLiteral() {
4720 ASSERT('0' <= current() && current() <= '7');
4721 // For compatibility with some other browsers (not all), we parse
4722 // up to three octal digits with a value below 256.
4723 uc32 value = current() - '0';
4724 Advance();
4725 if ('0' <= current() && current() <= '7') {
4726 value = value * 8 + current() - '0';
4727 Advance();
4728 if (value < 32 && '0' <= current() && current() <= '7') {
4729 value = value * 8 + current() - '0';
4730 Advance();
4731 }
4732 }
4733 return value;
4734}
4735
4736
4737bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4738 int start = position();
4739 uc32 val = 0;
4740 bool done = false;
4741 for (int i = 0; !done; i++) {
4742 uc32 c = current();
4743 int d = HexValue(c);
4744 if (d < 0) {
4745 Reset(start);
4746 return false;
4747 }
4748 val = val * 16 + d;
4749 Advance();
4750 if (i == length - 1) {
4751 done = true;
4752 }
4753 }
4754 *value = val;
4755 return true;
4756}
4757
4758
4759uc32 RegExpParser::ParseClassCharacterEscape() {
4760 ASSERT(current() == '\\');
4761 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4762 Advance();
4763 switch (current()) {
4764 case 'b':
4765 Advance();
4766 return '\b';
4767 // ControlEscape :: one of
4768 // f n r t v
4769 case 'f':
4770 Advance();
4771 return '\f';
4772 case 'n':
4773 Advance();
4774 return '\n';
4775 case 'r':
4776 Advance();
4777 return '\r';
4778 case 't':
4779 Advance();
4780 return '\t';
4781 case 'v':
4782 Advance();
4783 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004784 case 'c': {
4785 uc32 controlLetter = Next();
4786 uc32 letter = controlLetter & ~('A' ^ 'a');
4787 // For compatibility with JSC, inside a character class
4788 // we also accept digits and underscore as control characters.
4789 if ((controlLetter >= '0' && controlLetter <= '9') ||
4790 controlLetter == '_' ||
4791 (letter >= 'A' && letter <= 'Z')) {
4792 Advance(2);
4793 // Control letters mapped to ASCII control characters in the range
4794 // 0x00-0x1f.
4795 return controlLetter & 0x1f;
4796 }
4797 // We match JSC in reading the backslash as a literal
4798 // character instead of as starting an escape.
4799 return '\\';
4800 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004801 case '0': case '1': case '2': case '3': case '4': case '5':
4802 case '6': case '7':
4803 // For compatibility, we interpret a decimal escape that isn't
4804 // a back reference (and therefore either \0 or not valid according
4805 // to the specification) as a 1..3 digit octal character code.
4806 return ParseOctalLiteral();
4807 case 'x': {
4808 Advance();
4809 uc32 value;
4810 if (ParseHexEscape(2, &value)) {
4811 return value;
4812 }
4813 // If \x is not followed by a two-digit hexadecimal, treat it
4814 // as an identity escape.
4815 return 'x';
4816 }
4817 case 'u': {
4818 Advance();
4819 uc32 value;
4820 if (ParseHexEscape(4, &value)) {
4821 return value;
4822 }
4823 // If \u is not followed by a four-digit hexadecimal, treat it
4824 // as an identity escape.
4825 return 'u';
4826 }
4827 default: {
4828 // Extended identity escape. We accept any character that hasn't
4829 // been matched by a more specific case, not just the subset required
4830 // by the ECMAScript specification.
4831 uc32 result = current();
4832 Advance();
4833 return result;
4834 }
4835 }
4836 return 0;
4837}
4838
4839
4840CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4841 ASSERT_EQ(0, *char_class);
4842 uc32 first = current();
4843 if (first == '\\') {
4844 switch (Next()) {
4845 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4846 *char_class = Next();
4847 Advance(2);
4848 return CharacterRange::Singleton(0); // Return dummy value.
4849 }
4850 case kEndMarker:
4851 return ReportError(CStrVector("\\ at end of pattern"));
4852 default:
4853 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4854 return CharacterRange::Singleton(c);
4855 }
4856 } else {
4857 Advance();
4858 return CharacterRange::Singleton(first);
4859 }
4860}
4861
4862
Ben Murdochb0fe1622011-05-05 13:52:32 +01004863static const uc16 kNoCharClass = 0;
4864
4865// Adds range or pre-defined character class to character ranges.
4866// If char_class is not kInvalidClass, it's interpreted as a class
4867// escape (i.e., 's' means whitespace, from '\s').
4868static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4869 uc16 char_class,
4870 CharacterRange range) {
4871 if (char_class != kNoCharClass) {
4872 CharacterRange::AddClassEscape(char_class, ranges);
4873 } else {
4874 ranges->Add(range);
4875 }
4876}
4877
4878
Steve Blocka7e24c12009-10-30 11:49:00 +00004879RegExpTree* RegExpParser::ParseCharacterClass() {
4880 static const char* kUnterminated = "Unterminated character class";
4881 static const char* kRangeOutOfOrder = "Range out of order in character class";
4882
4883 ASSERT_EQ(current(), '[');
4884 Advance();
4885 bool is_negated = false;
4886 if (current() == '^') {
4887 is_negated = true;
4888 Advance();
4889 }
4890 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4891 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004892 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004893 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004894 if (current() == '-') {
4895 Advance();
4896 if (current() == kEndMarker) {
4897 // If we reach the end we break out of the loop and let the
4898 // following code report an error.
4899 break;
4900 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004901 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004902 ranges->Add(CharacterRange::Singleton('-'));
4903 break;
4904 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004905 uc16 char_class_2 = kNoCharClass;
4906 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4907 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4908 // Either end is an escaped character class. Treat the '-' verbatim.
4909 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004910 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004911 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004912 continue;
4913 }
4914 if (first.from() > next.to()) {
4915 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4916 }
4917 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4918 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004919 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004920 }
4921 }
4922 if (!has_more()) {
4923 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4924 }
4925 Advance();
4926 if (ranges->length() == 0) {
4927 ranges->Add(CharacterRange::Everything());
4928 is_negated = !is_negated;
4929 }
4930 return new RegExpCharacterClass(ranges, is_negated);
4931}
4932
4933
4934// ----------------------------------------------------------------------------
4935// The Parser interface.
4936
Steve Blocka7e24c12009-10-30 11:49:00 +00004937ParserMessage::~ParserMessage() {
4938 for (int i = 0; i < args().length(); i++)
4939 DeleteArray(args()[i]);
4940 DeleteArray(args().start());
4941}
4942
4943
4944ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01004945 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00004946}
4947
4948
4949int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01004950 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00004951}
4952
4953
Leon Clarkef7060e22010-06-03 12:02:55 +01004954const char* ScriptDataImpl::Data() {
4955 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00004956}
4957
4958
Leon Clarkee46be812010-01-19 14:06:41 +00004959bool ScriptDataImpl::HasError() {
4960 return has_error();
4961}
4962
4963
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004964void ScriptDataImpl::Initialize() {
4965 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004966 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
4967 function_index_ = PreparseDataConstants::kHeaderSize;
4968 int symbol_data_offset = PreparseDataConstants::kHeaderSize
4969 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004970 if (store_.length() > symbol_data_offset) {
4971 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
4972 } else {
4973 // Partial preparse causes no symbol information.
4974 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4975 }
4976 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4977 }
4978}
4979
4980
4981int ScriptDataImpl::ReadNumber(byte** source) {
4982 // Reads a number from symbol_data_ in base 128. The most significant
4983 // bit marks that there are more digits.
4984 // If the first byte is 0x80 (kNumberTerminator), it would normally
4985 // represent a leading zero. Since that is useless, and therefore won't
4986 // appear as the first digit of any actual value, it is used to
4987 // mark the end of the input stream.
4988 byte* data = *source;
4989 if (data >= symbol_data_end_) return -1;
4990 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004991 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004992 // End of stream marker.
4993 return -1;
4994 }
4995 int result = input & 0x7f;
4996 data++;
4997 while ((input & 0x80u) != 0) {
4998 if (data >= symbol_data_end_) return -1;
4999 input = *data;
5000 result = (result << 7) | (input & 0x7f);
5001 data++;
5002 }
5003 *source = data;
5004 return result;
5005}
5006
5007
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005008// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005009static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005010 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01005011 ParserRecorder* recorder) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005012 V8JavaScriptScanner scanner;
Steve Block9fac8402011-05-12 15:51:54 +01005013 scanner.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005014 intptr_t stack_limit = StackGuard::real_climit();
5015 if (!preparser::PreParser::PreParseProgram(&scanner,
5016 recorder,
5017 allow_lazy,
5018 stack_limit)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005019 Top::StackOverflow();
5020 return NULL;
5021 }
5022
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005023 // Extract the accumulated data from the recorder as a single
5024 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005025 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005026 return new ScriptDataImpl(store);
5027}
5028
5029
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005030// Preparse, but only collect data that is immediately useful,
5031// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005032ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005033 v8::Extension* extension) {
5034 bool allow_lazy = FLAG_lazy && (extension == NULL);
5035 if (!allow_lazy) {
5036 // Partial preparsing is only about lazily compiled functions.
5037 // If we don't allow lazy compilation, the log data will be empty.
5038 return NULL;
5039 }
5040 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005041 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005042}
5043
5044
Ben Murdochb0fe1622011-05-05 13:52:32 +01005045ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005046 v8::Extension* extension) {
5047 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005048 bool allow_lazy = FLAG_lazy && (extension == NULL);
5049 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005050 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005051}
5052
5053
5054bool RegExpParser::ParseRegExp(FlatStringReader* input,
5055 bool multiline,
5056 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005057 ASSERT(result != NULL);
5058 RegExpParser parser(input, &result->error, multiline);
5059 RegExpTree* tree = parser.ParsePattern();
5060 if (parser.failed()) {
5061 ASSERT(tree == NULL);
5062 ASSERT(!result->error.is_null());
5063 } else {
5064 ASSERT(tree != NULL);
5065 ASSERT(result->error.is_null());
5066 result->tree = tree;
5067 int capture_count = parser.captures_started();
5068 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5069 result->contains_anchor = parser.contains_anchor();
5070 result->capture_count = capture_count;
5071 }
5072 return !parser.failed();
5073}
5074
5075
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005076bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005077 ASSERT(info->function() == NULL);
5078 FunctionLiteral* result = NULL;
5079 Handle<Script> script = info->script();
5080 if (info->is_lazy()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005081 Parser parser(script, true, NULL, NULL);
Ben Murdochf87a2032010-10-22 12:50:53 +01005082 result = parser.ParseLazy(info->shared_info());
Leon Clarke4515c472010-02-03 11:58:03 +00005083 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01005084 bool allow_natives_syntax =
5085 FLAG_allow_natives_syntax || Bootstrapper::IsActive();
5086 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005087 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01005088 if (pre_data != NULL && pre_data->has_error()) {
5089 Scanner::Location loc = pre_data->MessageLocation();
5090 const char* message = pre_data->BuildMessage();
5091 Vector<const char*> args = pre_data->BuildArgs();
5092 parser.ReportMessageAt(loc, message, args);
5093 DeleteArray(message);
5094 for (int i = 0; i < args.length(); i++) {
5095 DeleteArray(args[i]);
5096 }
5097 DeleteArray(args.start());
5098 ASSERT(Top::has_pending_exception());
5099 } else {
5100 Handle<String> source = Handle<String>(String::cast(script->source()));
Steve Block1e0659c2011-05-24 12:43:12 +01005101 result = parser.ParseProgram(source,
5102 info->is_global(),
5103 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01005104 }
Leon Clarke4515c472010-02-03 11:58:03 +00005105 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005106
5107 info->SetFunction(result);
5108 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005109}
5110
Steve Blocka7e24c12009-10-30 11:49:00 +00005111} } // namespace v8::internal