blob: 6ad9ab3162bf63c42f0fcde5d02265c6a264853a [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 Blocka7e24c12009-10-30 11:49:00 +0000286 private:
Steve Block3ce2e202009-11-05 08:53:23 +0000287 // Captures the number of literals that need materialization in the
288 // function. Includes regexp literals, and boilerplate for object
289 // and array literals.
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 int materialized_literal_count_;
291
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 // Properties count estimation.
293 int expected_property_count_;
294
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100295 // Keeps track of assignments to properties of this. Used for
296 // optimizing constructors.
Steve Blocka7e24c12009-10-30 11:49:00 +0000297 bool only_simple_this_property_assignments_;
298 Handle<FixedArray> this_property_assignments_;
299
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100300 // Captures the number of loops inside the scope.
301 int loop_count_;
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 // Bookkeeping
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800304 TemporaryScope** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 TemporaryScope* parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000306};
307
308
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800309TemporaryScope::TemporaryScope(TemporaryScope** variable)
Steve Blocka7e24c12009-10-30 11:49:00 +0000310 : materialized_literal_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 expected_property_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000312 only_simple_this_property_assignments_(false),
313 this_property_assignments_(Factory::empty_fixed_array()),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100314 loop_count_(0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800315 variable_(variable),
316 parent_(*variable) {
317 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000318}
319
320
321TemporaryScope::~TemporaryScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800322 *variable_ = parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000323}
324
325
Steve Block9fac8402011-05-12 15:51:54 +0100326Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800327 // Length of symbol cache is the number of identified symbols.
328 // If we are larger than that, or negative, it's not a cached symbol.
329 // This might also happen if there is no preparser symbol data, even
330 // if there is some preparser data.
331 if (static_cast<unsigned>(symbol_id)
332 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100333 if (scanner().is_literal_ascii()) {
334 return Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
335 } else {
336 return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
337 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800338 }
Steve Block9fac8402011-05-12 15:51:54 +0100339 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800340}
341
342
Steve Block9fac8402011-05-12 15:51:54 +0100343Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800344 // Make sure the cache is large enough to hold the symbol identifier.
345 if (symbol_cache_.length() <= symbol_id) {
346 // Increase length to index + 1.
347 symbol_cache_.AddBlock(Handle<String>::null(),
348 symbol_id + 1 - symbol_cache_.length());
349 }
350 Handle<String> result = symbol_cache_.at(symbol_id);
351 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100352 if (scanner().is_literal_ascii()) {
353 result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
354 } else {
355 result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
356 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800357 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100358 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000359 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800360 Counters::total_preparse_symbols_skipped.Increment();
361 return result;
362}
Steve Blocka7e24c12009-10-30 11:49:00 +0000363
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800364
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100365FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
366 // The current pre-data entry must be a FunctionEntry with the given
367 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100368 if ((function_index_ + FunctionEntry::kSize <= store_.length())
369 && (static_cast<int>(store_[function_index_]) == start)) {
370 int index = function_index_;
371 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100372 return FunctionEntry(store_.SubVector(index,
373 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 }
375 return FunctionEntry();
376}
377
378
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100379int ScriptDataImpl::GetSymbolIdentifier() {
380 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100381}
382
383
Iain Merrick9ac36c92010-09-13 15:29:50 +0100384bool ScriptDataImpl::SanityCheck() {
385 // Check that the header data is valid and doesn't specify
386 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800387 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
388 if (magic() != PreparseDataConstants::kMagicNumber) return false;
389 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100390 if (has_error()) {
391 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800392 if (store_.length() <= PreparseDataConstants::kHeaderSize
393 + PreparseDataConstants::kMessageTextPos) {
394 return false;
395 }
396 if (Read(PreparseDataConstants::kMessageStartPos) >
397 Read(PreparseDataConstants::kMessageEndPos)) {
398 return false;
399 }
400 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
401 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100402 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800403 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
404 return false;
405 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100406 int length = static_cast<int>(Read(pos));
407 if (length < 0) return false;
408 pos += 1 + length;
409 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800410 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
411 return false;
412 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100413 return true;
414 }
415 // Check that the space allocated for function entries is sane.
416 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800417 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100418 if (functions_size < 0) return false;
419 if (functions_size % FunctionEntry::kSize != 0) return false;
420 // Check that the count of symbols is non-negative.
421 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800422 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100423 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100424 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100425 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800426 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100427 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 return true;
429}
430
431
Steve Block59151502010-09-22 15:07:15 +0100432
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100433const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 int length = start[0];
435 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100436 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100438 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 result[length] = '\0';
440 if (chars != NULL) *chars = length;
441 return result;
442}
443
Steve Blocka7e24c12009-10-30 11:49:00 +0000444Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800445 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
446 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 return Scanner::Location(beg_pos, end_pos);
448}
449
450
451const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800452 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100453 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000454}
455
456
457Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800458 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000459 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100460 // Position after text found by skipping past length field and
461 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800462 int pos = PreparseDataConstants::kMessageTextPos + 1
463 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 for (int i = 0; i < arg_count; i++) {
465 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100466 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 pos += count + 1;
468 }
469 return Vector<const char*>(array, arg_count);
470}
471
472
473unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800474 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000475}
476
477
478unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800479 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000480}
481
482
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800483Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000484 Scope* result = new Scope(parent, type);
485 result->Initialize(inside_with);
486 return result;
487}
488
Steve Blocka7e24c12009-10-30 11:49:00 +0000489// ----------------------------------------------------------------------------
490// Target is a support class to facilitate manipulation of the
491// Parser's target_stack_ (the stack of potential 'break' and
492// 'continue' statement targets). Upon construction, a new target is
493// added; it is removed upon destruction.
494
495class Target BASE_EMBEDDED {
496 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800497 Target(Target** variable, AstNode* node)
498 : variable_(variable), node_(node), previous_(*variable) {
499 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000500 }
501
502 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800503 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 }
505
506 Target* previous() { return previous_; }
507 AstNode* node() { return node_; }
508
509 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800510 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 AstNode* node_;
512 Target* previous_;
513};
514
515
516class TargetScope BASE_EMBEDDED {
517 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800518 explicit TargetScope(Target** variable)
519 : variable_(variable), previous_(*variable) {
520 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 }
522
523 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800524 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 }
526
527 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800528 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 Target* previous_;
530};
531
532
533// ----------------------------------------------------------------------------
534// LexicalScope is a support class to facilitate manipulation of the
535// Parser's scope stack. The constructor sets the parser's top scope
536// to the incoming scope, and the destructor resets it.
537
538class LexicalScope BASE_EMBEDDED {
539 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800540 LexicalScope(Scope** scope_variable,
541 int* with_nesting_level_variable,
542 Scope* scope)
543 : scope_variable_(scope_variable),
544 with_nesting_level_variable_(with_nesting_level_variable),
545 prev_scope_(*scope_variable),
546 prev_level_(*with_nesting_level_variable) {
547 *scope_variable = scope;
548 *with_nesting_level_variable = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000549 }
550
551 ~LexicalScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800552 (*scope_variable_)->Leave();
553 *scope_variable_ = prev_scope_;
554 *with_nesting_level_variable_ = prev_level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 }
556
557 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800558 Scope** scope_variable_;
559 int* with_nesting_level_variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 Scope* prev_scope_;
561 int prev_level_;
562};
563
564
565// ----------------------------------------------------------------------------
566// The CHECK_OK macro is a convenient macro to enforce error
567// handling for functions that may fail (by returning !*ok).
568//
569// CAUTION: This macro appends extra statements after a call,
570// thus it must never be used where only a single statement
571// is correct (e.g. an if statement branch w/o braces)!
572
573#define CHECK_OK ok); \
574 if (!*ok) return NULL; \
575 ((void)0
576#define DUMMY ) // to make indentation work
577#undef DUMMY
578
579#define CHECK_FAILED /**/); \
580 if (failed_) return NULL; \
581 ((void)0
582#define DUMMY ) // to make indentation work
583#undef DUMMY
584
585// ----------------------------------------------------------------------------
586// Implementation of Parser
587
588Parser::Parser(Handle<Script> script,
589 bool allow_natives_syntax,
590 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000591 ScriptDataImpl* pre_data)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800592 : symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
593 script_(script),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100594 scanner_(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 top_scope_(NULL),
596 with_nesting_level_(0),
597 temp_scope_(NULL),
598 target_stack_(NULL),
599 allow_natives_syntax_(allow_natives_syntax),
600 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100601 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100602 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100603 stack_overflow_(false),
604 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100605 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000606}
607
608
Steve Blocka7e24c12009-10-30 11:49:00 +0000609FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Blocka7e24c12009-10-30 11:49:00 +0000610 bool in_global_context) {
611 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
612
613 HistogramTimerScope timer(&Counters::parse);
614 Counters::total_parse_size.Increment(source->length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100615 fni_ = new FuncNameInferrer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000616
617 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100618 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100619 if (source->IsExternalTwoByteString()) {
620 // Notice that the stream is destroyed at the end of the branch block.
621 // The last line of the blocks can't be moved outside, even though they're
622 // identical calls.
623 ExternalTwoByteStringUC16CharacterStream stream(
624 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100625 scanner_.Initialize(&stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100626 return DoParseProgram(source, in_global_context, &zone_scope);
627 } else {
628 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100629 scanner_.Initialize(&stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100630 return DoParseProgram(source, in_global_context, &zone_scope);
631 }
632}
633
634
635FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
636 bool in_global_context,
637 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000638 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100639 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000640
641 // Compute the parsing mode.
642 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
643 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
644
645 Scope::Type type =
646 in_global_context
647 ? Scope::GLOBAL_SCOPE
648 : Scope::EVAL_SCOPE;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800649 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000650
651 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800652 { Scope* scope = NewScope(top_scope_, type, inside_with());
653 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
654 scope);
655 TemporaryScope temp_scope(&this->temp_scope_);
656 ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 bool ok = true;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800658 ParseSourceElements(body, Token::EOS, &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000659 if (ok) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800660 result = new FunctionLiteral(
Steve Blocka7e24c12009-10-30 11:49:00 +0000661 no_name,
662 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800663 body,
Steve Blocka7e24c12009-10-30 11:49:00 +0000664 temp_scope.materialized_literal_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000665 temp_scope.expected_property_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 temp_scope.only_simple_this_property_assignments(),
667 temp_scope.this_property_assignments(),
668 0,
669 0,
670 source->length(),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100671 false,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800672 temp_scope.ContainsLoops());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100673 } else if (stack_overflow_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 Top::StackOverflow();
675 }
676 }
677
678 // Make sure the target stack is empty.
679 ASSERT(target_stack_ == NULL);
680
681 // If there was a syntax error we have to get rid of the AST
682 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100683 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000684 return result;
685}
686
Ben Murdochf87a2032010-10-22 12:50:53 +0100687FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000688 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
689 HistogramTimerScope timer(&Counters::parse_lazy);
Ben Murdochf87a2032010-10-22 12:50:53 +0100690 Handle<String> source(String::cast(script_->source()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000691 Counters::total_parse_size.Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000692
Ben Murdochb0fe1622011-05-05 13:52:32 +0100693 // Initialize parser state.
694 source->TryFlatten();
695 if (source->IsExternalTwoByteString()) {
696 ExternalTwoByteStringUC16CharacterStream stream(
697 Handle<ExternalTwoByteString>::cast(source),
698 info->start_position(),
699 info->end_position());
700 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
701 return result;
702 } else {
703 GenericStringUC16CharacterStream stream(source,
704 info->start_position(),
705 info->end_position());
706 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
707 return result;
708 }
709}
710
711
712FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
713 UC16CharacterStream* source,
714 ZoneScope* zone_scope) {
Steve Block9fac8402011-05-12 15:51:54 +0100715 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100716 ASSERT(target_stack_ == NULL);
717
Ben Murdochf87a2032010-10-22 12:50:53 +0100718 Handle<String> name(String::cast(info->name()));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100719 fni_ = new FuncNameInferrer();
720 fni_->PushEnclosingName(name);
721
Steve Blocka7e24c12009-10-30 11:49:00 +0000722 mode_ = PARSE_EAGERLY;
723
724 // Place holder for the result.
725 FunctionLiteral* result = NULL;
726
727 {
728 // Parse the function literal.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800729 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800731 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
732 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
733 scope);
734 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000735
Ben Murdochf87a2032010-10-22 12:50:53 +0100736 FunctionLiteralType type =
737 info->is_expression() ? EXPRESSION : DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000738 bool ok = true;
739 result = ParseFunctionLiteral(name, RelocInfo::kNoPosition, type, &ok);
740 // Make sure the results agree.
741 ASSERT(ok == (result != NULL));
742 // The only errors should be stack overflows.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100743 ASSERT(ok || stack_overflow_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000744 }
745
746 // Make sure the target stack is empty.
747 ASSERT(target_stack_ == NULL);
748
749 // If there was a stack overflow we have to get rid of AST and it is
750 // not safe to do before scope has been deleted.
751 if (result == NULL) {
752 Top::StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100753 zone_scope->DeleteOnExit();
754 } else {
755 Handle<String> inferred_name(info->inferred_name());
756 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000757 }
758 return result;
759}
760
Ben Murdochf87a2032010-10-22 12:50:53 +0100761
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800762Handle<String> Parser::GetSymbol(bool* ok) {
763 int symbol_id = -1;
764 if (pre_data() != NULL) {
765 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000766 }
Steve Block9fac8402011-05-12 15:51:54 +0100767 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000768}
Steve Blocka7e24c12009-10-30 11:49:00 +0000769
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800770
Steve Blocka7e24c12009-10-30 11:49:00 +0000771void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100772 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000773 ReportMessageAt(source_location, type, args);
774}
775
776
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800777void Parser::ReportMessageAt(Scanner::Location source_location,
778 const char* type,
779 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100781 source_location.beg_pos,
782 source_location.end_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000783 Handle<JSArray> array = Factory::NewJSArray(args.length());
784 for (int i = 0; i < args.length(); i++) {
785 SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i])));
786 }
787 Handle<Object> result = Factory::NewSyntaxError(type, array);
788 Top::Throw(*result, &location);
789}
790
791
Ben Murdochb8e0da22011-05-16 14:20:40 +0100792void Parser::ReportMessageAt(Scanner::Location source_location,
793 const char* type,
794 Vector<Handle<String> > args) {
795 MessageLocation location(script_,
796 source_location.beg_pos,
797 source_location.end_pos);
798 Handle<JSArray> array = Factory::NewJSArray(args.length());
799 for (int i = 0; i < args.length(); i++) {
800 SetElement(array, i, args[i]);
801 }
802 Handle<Object> result = Factory::NewSyntaxError(type, array);
803 Top::Throw(*result, &location);
804}
805
806
Steve Blocka7e24c12009-10-30 11:49:00 +0000807// Base class containing common code for the different finder classes used by
808// the parser.
809class ParserFinder {
810 protected:
811 ParserFinder() {}
812 static Assignment* AsAssignment(Statement* stat) {
813 if (stat == NULL) return NULL;
814 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
815 if (exp_stat == NULL) return NULL;
816 return exp_stat->expression()->AsAssignment();
817 }
818};
819
820
821// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000822// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000823class InitializationBlockFinder : public ParserFinder {
824 public:
825 InitializationBlockFinder()
826 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
827
828 ~InitializationBlockFinder() {
829 if (InBlock()) EndBlock();
830 }
831
832 void Update(Statement* stat) {
833 Assignment* assignment = AsAssignment(stat);
834 if (InBlock()) {
835 if (BlockContinues(assignment)) {
836 UpdateBlock(assignment);
837 } else {
838 EndBlock();
839 }
840 }
841 if (!InBlock() && (assignment != NULL) &&
842 (assignment->op() == Token::ASSIGN)) {
843 StartBlock(assignment);
844 }
845 }
846
847 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800848 // The minimum number of contiguous assignment that will
849 // be treated as an initialization block. Benchmarks show that
850 // the overhead exceeds the savings below this limit.
851 static const int kMinInitializationBlock = 3;
852
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 // Returns true if the expressions appear to denote the same object.
854 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000855 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 static bool SameObject(Expression* e1, Expression* e2) {
857 VariableProxy* v1 = e1->AsVariableProxy();
858 VariableProxy* v2 = e2->AsVariableProxy();
859 if (v1 != NULL && v2 != NULL) {
860 return v1->name()->Equals(*v2->name());
861 }
862 Property* p1 = e1->AsProperty();
863 Property* p2 = e2->AsProperty();
864 if ((p1 == NULL) || (p2 == NULL)) return false;
865 Literal* key1 = p1->key()->AsLiteral();
866 Literal* key2 = p2->key()->AsLiteral();
867 if ((key1 == NULL) || (key2 == NULL)) return false;
868 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
869 return false;
870 }
871 String* name1 = String::cast(*key1->handle());
872 String* name2 = String::cast(*key2->handle());
873 if (!name1->Equals(name2)) return false;
874 return SameObject(p1->obj(), p2->obj());
875 }
876
877 // Returns true if the expressions appear to denote different properties
878 // of the same object.
879 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
880 Property* p1 = e1->AsProperty();
881 Property* p2 = e2->AsProperty();
882 if ((p1 == NULL) || (p2 == NULL)) return false;
883 return SameObject(p1->obj(), p2->obj());
884 }
885
886 bool BlockContinues(Assignment* assignment) {
887 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
888 if (assignment->op() != Token::ASSIGN) return false;
889 return PropertyOfSameObject(first_in_block_->target(),
890 assignment->target());
891 }
892
893 void StartBlock(Assignment* assignment) {
894 first_in_block_ = assignment;
895 last_in_block_ = assignment;
896 block_size_ = 1;
897 }
898
899 void UpdateBlock(Assignment* assignment) {
900 last_in_block_ = assignment;
901 ++block_size_;
902 }
903
904 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800905 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000906 first_in_block_->mark_block_start();
907 last_in_block_->mark_block_end();
908 }
909 last_in_block_ = first_in_block_ = NULL;
910 block_size_ = 0;
911 }
912
913 bool InBlock() { return first_in_block_ != NULL; }
914
915 Assignment* first_in_block_;
916 Assignment* last_in_block_;
917 int block_size_;
918
919 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
920};
921
922
923// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
924// this.x = ...;, where x is a named property. It also determines whether a
925// function contains only assignments of this type.
926class ThisNamedPropertyAssigmentFinder : public ParserFinder {
927 public:
928 ThisNamedPropertyAssigmentFinder()
Steve Blockd0582a62009-12-15 09:54:21 +0000929 : only_simple_this_property_assignments_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000930 names_(NULL),
931 assigned_arguments_(NULL),
932 assigned_constants_(NULL) {}
933
934 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000935 // Bail out if function already has property assignment that are
936 // not simple this property assignments.
937 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000938 return;
939 }
940
941 // Check whether this statement is of the form this.x = ...;
942 Assignment* assignment = AsAssignment(stat);
943 if (IsThisPropertyAssignment(assignment)) {
944 HandleThisPropertyAssignment(scope, assignment);
945 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000946 only_simple_this_property_assignments_ = false;
947 }
948 }
949
Steve Blocka7e24c12009-10-30 11:49:00 +0000950 // Returns whether only statements of the form this.x = y; where y is either a
951 // constant or a function argument was encountered.
952 bool only_simple_this_property_assignments() {
953 return only_simple_this_property_assignments_;
954 }
955
956 // Returns a fixed array containing three elements for each assignment of the
957 // form this.x = y;
958 Handle<FixedArray> GetThisPropertyAssignments() {
959 if (names_ == NULL) {
960 return Factory::empty_fixed_array();
961 }
962 ASSERT(names_ != NULL);
963 ASSERT(assigned_arguments_ != NULL);
964 ASSERT_EQ(names_->length(), assigned_arguments_->length());
965 ASSERT_EQ(names_->length(), assigned_constants_->length());
966 Handle<FixedArray> assignments =
967 Factory::NewFixedArray(names_->length() * 3);
968 for (int i = 0; i < names_->length(); i++) {
969 assignments->set(i * 3, *names_->at(i));
970 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
971 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
972 }
973 return assignments;
974 }
975
976 private:
977 bool IsThisPropertyAssignment(Assignment* assignment) {
978 if (assignment != NULL) {
979 Property* property = assignment->target()->AsProperty();
980 return assignment->op() == Token::ASSIGN
981 && property != NULL
982 && property->obj()->AsVariableProxy() != NULL
983 && property->obj()->AsVariableProxy()->is_this();
984 }
985 return false;
986 }
987
988 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +0100989 // Check that the property assigned to is a named property, which is not
990 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 Property* property = assignment->target()->AsProperty();
992 ASSERT(property != NULL);
993 Literal* literal = property->key()->AsLiteral();
994 uint32_t dummy;
995 if (literal != NULL &&
996 literal->handle()->IsString() &&
Steve Block6ded16b2010-05-10 14:33:55 +0100997 !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +0000998 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
999 Handle<String> key = Handle<String>::cast(literal->handle());
1000
1001 // Check whether the value assigned is either a constant or matches the
1002 // name of one of the arguments to the function.
1003 if (assignment->value()->AsLiteral() != NULL) {
1004 // Constant assigned.
1005 Literal* literal = assignment->value()->AsLiteral();
1006 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001007 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001008 } else if (assignment->value()->AsVariableProxy() != NULL) {
1009 // Variable assigned.
1010 Handle<String> name =
1011 assignment->value()->AsVariableProxy()->name();
1012 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001013 for (int i = 0; i < scope->num_parameters(); i++) {
1014 if (*scope->parameter(i)->name() == *name) {
1015 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001016 AssignmentFromParameter(key, i);
1017 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001018 }
1019 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001020 }
1021 }
Steve Blockd0582a62009-12-15 09:54:21 +00001022 // It is not a simple "this.x = value;" assignment with a constant
1023 // or parameter value.
1024 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001025 }
1026
1027 void AssignmentFromParameter(Handle<String> name, int index) {
1028 EnsureAllocation();
1029 names_->Add(name);
1030 assigned_arguments_->Add(index);
1031 assigned_constants_->Add(Factory::undefined_value());
1032 }
1033
1034 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
1035 EnsureAllocation();
1036 names_->Add(name);
1037 assigned_arguments_->Add(-1);
1038 assigned_constants_->Add(value);
1039 }
1040
Steve Blockd0582a62009-12-15 09:54:21 +00001041 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001042 // The this assignment is not a simple one.
1043 only_simple_this_property_assignments_ = false;
1044 }
1045
1046 void EnsureAllocation() {
1047 if (names_ == NULL) {
1048 ASSERT(assigned_arguments_ == NULL);
1049 ASSERT(assigned_constants_ == NULL);
1050 names_ = new ZoneStringList(4);
1051 assigned_arguments_ = new ZoneList<int>(4);
1052 assigned_constants_ = new ZoneObjectList(4);
1053 }
1054 }
1055
Steve Blocka7e24c12009-10-30 11:49:00 +00001056 bool only_simple_this_property_assignments_;
1057 ZoneStringList* names_;
1058 ZoneList<int>* assigned_arguments_;
1059 ZoneObjectList* assigned_constants_;
1060};
1061
1062
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001063void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001064 int end_token,
1065 bool* ok) {
1066 // SourceElements ::
1067 // (Statement)* <end_token>
1068
1069 // Allocate a target stack to use for this set of source
1070 // elements. This way, all scripts and functions get their own
1071 // target stack thus avoiding illegal breaks and continues across
1072 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001073 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001074
1075 ASSERT(processor != NULL);
1076 InitializationBlockFinder block_finder;
1077 ThisNamedPropertyAssigmentFinder this_property_assignment_finder;
1078 while (peek() != end_token) {
1079 Statement* stat = ParseStatement(NULL, CHECK_OK);
1080 if (stat == NULL || stat->IsEmpty()) continue;
1081 // We find and mark the initialization blocks on top level code only.
1082 // This is because the optimization prevents reuse of the map transitions,
1083 // so it should be used only for code that will only be run once.
1084 if (top_scope_->is_global_scope()) {
1085 block_finder.Update(stat);
1086 }
1087 // Find and mark all assignments to named properties in this (this.x =)
1088 if (top_scope_->is_function_scope()) {
1089 this_property_assignment_finder.Update(top_scope_, stat);
1090 }
1091 processor->Add(stat);
1092 }
1093
1094 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001095 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001096 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001097 this_property_assignment_finder.only_simple_this_property_assignments()
1098 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001099 if (only_simple_this_property_assignments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 temp_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001101 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001102 this_property_assignment_finder.GetThisPropertyAssignments());
1103 }
1104 }
1105 return 0;
1106}
1107
1108
1109Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1110 // Statement ::
1111 // Block
1112 // VariableStatement
1113 // EmptyStatement
1114 // ExpressionStatement
1115 // IfStatement
1116 // IterationStatement
1117 // ContinueStatement
1118 // BreakStatement
1119 // ReturnStatement
1120 // WithStatement
1121 // LabelledStatement
1122 // SwitchStatement
1123 // ThrowStatement
1124 // TryStatement
1125 // DebuggerStatement
1126
1127 // Note: Since labels can only be used by 'break' and 'continue'
1128 // statements, which themselves are only valid within blocks,
1129 // iterations or 'switch' statements (i.e., BreakableStatements),
1130 // labels can be simply ignored in all other cases; except for
1131 // trivial labeled break statements 'label: break label' which is
1132 // parsed into an empty statement.
1133
1134 // Keep the source position of the statement
1135 int statement_pos = scanner().peek_location().beg_pos;
1136 Statement* stmt = NULL;
1137 switch (peek()) {
1138 case Token::LBRACE:
1139 return ParseBlock(labels, ok);
1140
1141 case Token::CONST: // fall through
1142 case Token::VAR:
1143 stmt = ParseVariableStatement(ok);
1144 break;
1145
1146 case Token::SEMICOLON:
1147 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001148 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001149
1150 case Token::IF:
1151 stmt = ParseIfStatement(labels, ok);
1152 break;
1153
1154 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001155 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001156 break;
1157
1158 case Token::WHILE:
1159 stmt = ParseWhileStatement(labels, ok);
1160 break;
1161
1162 case Token::FOR:
1163 stmt = ParseForStatement(labels, ok);
1164 break;
1165
1166 case Token::CONTINUE:
1167 stmt = ParseContinueStatement(ok);
1168 break;
1169
1170 case Token::BREAK:
1171 stmt = ParseBreakStatement(labels, ok);
1172 break;
1173
1174 case Token::RETURN:
1175 stmt = ParseReturnStatement(ok);
1176 break;
1177
1178 case Token::WITH:
1179 stmt = ParseWithStatement(labels, ok);
1180 break;
1181
1182 case Token::SWITCH:
1183 stmt = ParseSwitchStatement(labels, ok);
1184 break;
1185
1186 case Token::THROW:
1187 stmt = ParseThrowStatement(ok);
1188 break;
1189
1190 case Token::TRY: {
1191 // NOTE: It is somewhat complicated to have labels on
1192 // try-statements. When breaking out of a try-finally statement,
1193 // one must take great care not to treat it as a
1194 // fall-through. It is much easier just to wrap the entire
1195 // try-statement in a statement block and put the labels there
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001196 Block* result = new Block(labels, 1, false);
1197 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 TryStatement* statement = ParseTryStatement(CHECK_OK);
1199 if (statement) {
1200 statement->set_statement_pos(statement_pos);
1201 }
1202 if (result) result->AddStatement(statement);
1203 return result;
1204 }
1205
1206 case Token::FUNCTION:
1207 return ParseFunctionDeclaration(ok);
1208
1209 case Token::NATIVE:
1210 return ParseNativeDeclaration(ok);
1211
1212 case Token::DEBUGGER:
1213 stmt = ParseDebuggerStatement(ok);
1214 break;
1215
1216 default:
1217 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1218 }
1219
1220 // Store the source position of the statement
1221 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1222 return stmt;
1223}
1224
1225
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001226VariableProxy* Parser::Declare(Handle<String> name,
1227 Variable::Mode mode,
1228 FunctionLiteral* fun,
1229 bool resolve,
1230 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 Variable* var = NULL;
1232 // If we are inside a function, a declaration of a variable
1233 // is a truly local variable, and the scope of the variable
1234 // is always the function scope.
1235
1236 // If a function scope exists, then we can statically declare this
1237 // variable and also set its mode. In any case, a Declaration node
1238 // will be added to the scope so that the declaration can be added
1239 // to the corresponding activation frame at runtime if necessary.
1240 // For instance declarations inside an eval scope need to be added
1241 // to the calling function context.
1242 if (top_scope_->is_function_scope()) {
1243 // Declare the variable in the function scope.
1244 var = top_scope_->LocalLookup(name);
1245 if (var == NULL) {
1246 // Declare the name.
1247 var = top_scope_->DeclareLocal(name, mode);
1248 } else {
1249 // The name was declared before; check for conflicting
1250 // re-declarations. If the previous declaration was a const or the
1251 // current declaration is a const then we have a conflict. There is
1252 // similar code in runtime.cc in the Declare functions.
1253 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1254 // We only have vars and consts in declarations.
1255 ASSERT(var->mode() == Variable::VAR ||
1256 var->mode() == Variable::CONST);
1257 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1258 Handle<String> type_string =
1259 Factory::NewStringFromUtf8(CStrVector(type), TENURED);
1260 Expression* expression =
1261 NewThrowTypeError(Factory::redeclaration_symbol(),
1262 type_string, name);
1263 top_scope_->SetIllegalRedeclaration(expression);
1264 }
1265 }
1266 }
1267
1268 // We add a declaration node for every declaration. The compiler
1269 // will only generate code if necessary. In particular, declarations
1270 // for inner local variables that do not represent functions won't
1271 // result in any generated code.
1272 //
1273 // Note that we always add an unresolved proxy even if it's not
1274 // used, simply because we don't know in this method (w/o extra
1275 // parameters) if the proxy is needed or not. The proxy will be
1276 // bound during variable resolution time unless it was pre-bound
1277 // below.
1278 //
1279 // WARNING: This will lead to multiple declaration nodes for the
1280 // same variable if it is declared several times. This is not a
1281 // semantic issue as long as we keep the source order, but it may be
1282 // a performance issue since it may lead to repeated
1283 // Runtime::DeclareContextSlot() calls.
1284 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001285 top_scope_->AddDeclaration(new Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001286
1287 // For global const variables we bind the proxy to a variable.
1288 if (mode == Variable::CONST && top_scope_->is_global_scope()) {
1289 ASSERT(resolve); // should be set by all callers
1290 Variable::Kind kind = Variable::NORMAL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001291 var = new Variable(top_scope_, name, Variable::CONST, true, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001292 }
1293
1294 // If requested and we have a local variable, bind the proxy to the variable
1295 // at parse-time. This is used for functions (and consts) declared inside
1296 // statements: the corresponding function (or const) variable must be in the
1297 // function scope and not a statement-local scope, e.g. as provided with a
1298 // 'with' statement:
1299 //
1300 // with (obj) {
1301 // function f() {}
1302 // }
1303 //
1304 // which is translated into:
1305 //
1306 // with (obj) {
1307 // // in this case this is not: 'var f; f = function () {};'
1308 // var f = function () {};
1309 // }
1310 //
1311 // Note that if 'f' is accessed from inside the 'with' statement, it
1312 // will be allocated in the context (because we must be able to look
1313 // it up dynamically) but it will also be accessed statically, i.e.,
1314 // with a context slot index and a context chain length for this
1315 // initialization code. Thus, inside the 'with' statement, we need
1316 // both access to the static and the dynamic context chain; the
1317 // runtime needs to provide both.
1318 if (resolve && var != NULL) proxy->BindTo(var);
1319
1320 return proxy;
1321}
1322
1323
1324// Language extension which is only enabled for source files loaded
1325// through the API's extension mechanism. A native function
1326// declaration is resolved by looking up the function through a
1327// callback provided by the extension.
1328Statement* Parser::ParseNativeDeclaration(bool* ok) {
1329 if (extension_ == NULL) {
1330 ReportUnexpectedToken(Token::NATIVE);
1331 *ok = false;
1332 return NULL;
1333 }
1334
1335 Expect(Token::NATIVE, CHECK_OK);
1336 Expect(Token::FUNCTION, CHECK_OK);
1337 Handle<String> name = ParseIdentifier(CHECK_OK);
1338 Expect(Token::LPAREN, CHECK_OK);
1339 bool done = (peek() == Token::RPAREN);
1340 while (!done) {
1341 ParseIdentifier(CHECK_OK);
1342 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001343 if (!done) {
1344 Expect(Token::COMMA, CHECK_OK);
1345 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 }
1347 Expect(Token::RPAREN, CHECK_OK);
1348 Expect(Token::SEMICOLON, CHECK_OK);
1349
Steve Blocka7e24c12009-10-30 11:49:00 +00001350 // Make sure that the function containing the native declaration
1351 // isn't lazily compiled. The extension structures are only
1352 // accessible while parsing the first time not when reparsing
1353 // because of lazy compilation.
1354 top_scope_->ForceEagerCompilation();
1355
1356 // Compute the function template for the native function.
1357 v8::Handle<v8::FunctionTemplate> fun_template =
1358 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1359 ASSERT(!fun_template.IsEmpty());
1360
Steve Block6ded16b2010-05-10 14:33:55 +01001361 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001362 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1363 const int literals = fun->NumberOfLiterals();
1364 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001365 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001366 Handle<SharedFunctionInfo> shared =
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001367 Factory::NewSharedFunctionInfo(name, literals, code,
1368 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001369 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001370
Steve Block6ded16b2010-05-10 14:33:55 +01001371 // Copy the function data to the shared function info.
1372 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001373 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001374 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001375
1376 // TODO(1240846): It's weird that native function declarations are
1377 // introduced dynamically when we meet their declarations, whereas
1378 // other functions are setup when entering the surrounding scope.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001379 SharedFunctionInfoLiteral* lit = new SharedFunctionInfoLiteral(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001380 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001381 return new ExpressionStatement(
1382 new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001383}
1384
1385
1386Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1387 // FunctionDeclaration ::
1388 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1389 Expect(Token::FUNCTION, CHECK_OK);
1390 int function_token_position = scanner().location().beg_pos;
1391 Handle<String> name = ParseIdentifier(CHECK_OK);
1392 FunctionLiteral* fun = ParseFunctionLiteral(name,
1393 function_token_position,
1394 DECLARATION,
1395 CHECK_OK);
1396 // Even if we're not at the top-level of the global or a function
1397 // scope, we treat is as such and introduce the function with it's
1398 // initial value upon entering the corresponding scope.
1399 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001400 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001401}
1402
1403
1404Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1405 // Block ::
1406 // '{' Statement* '}'
1407
1408 // Note that a Block does not introduce a new execution scope!
1409 // (ECMA-262, 3rd, 12.2)
1410 //
1411 // Construct block expecting 16 statements.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001412 Block* result = new Block(labels, 16, false);
1413 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 Expect(Token::LBRACE, CHECK_OK);
1415 while (peek() != Token::RBRACE) {
1416 Statement* stat = ParseStatement(NULL, CHECK_OK);
1417 if (stat && !stat->IsEmpty()) result->AddStatement(stat);
1418 }
1419 Expect(Token::RBRACE, CHECK_OK);
1420 return result;
1421}
1422
1423
1424Block* Parser::ParseVariableStatement(bool* ok) {
1425 // VariableStatement ::
1426 // VariableDeclarations ';'
1427
1428 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature
1429 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK);
1430 ExpectSemicolon(CHECK_OK);
1431 return result;
1432}
1433
1434
1435// If the variable declaration declares exactly one non-const
1436// variable, then *var is set to that variable. In all other cases,
1437// *var is untouched; in particular, it is the caller's responsibility
1438// to initialize it properly. This mechanism is used for the parsing
1439// of 'for-in' loops.
1440Block* Parser::ParseVariableDeclarations(bool accept_IN,
1441 Expression** var,
1442 bool* ok) {
1443 // VariableDeclarations ::
1444 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1445
1446 Variable::Mode mode = Variable::VAR;
1447 bool is_const = false;
1448 if (peek() == Token::VAR) {
1449 Consume(Token::VAR);
1450 } else if (peek() == Token::CONST) {
1451 Consume(Token::CONST);
1452 mode = Variable::CONST;
1453 is_const = true;
1454 } else {
1455 UNREACHABLE(); // by current callers
1456 }
1457
1458 // The scope of a variable/const declared anywhere inside a function
1459 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1460 // transform a source-level variable/const declaration into a (Function)
1461 // Scope declaration, and rewrite the source-level initialization into an
1462 // assignment statement. We use a block to collect multiple assignments.
1463 //
1464 // We mark the block as initializer block because we don't want the
1465 // rewriter to add a '.result' assignment to such a block (to get compliant
1466 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1467 // reasons when pretty-printing. Also, unless an assignment (initialization)
1468 // is inside an initializer block, it is ignored.
1469 //
1470 // Create new block with one expected declaration.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001471 Block* block = new Block(NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001472 VariableProxy* last_var = NULL; // the last variable declared
1473 int nvars = 0; // the number of variables declared
1474 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001475 if (fni_ != NULL) fni_->Enter();
1476
Steve Blocka7e24c12009-10-30 11:49:00 +00001477 // Parse variable name.
1478 if (nvars > 0) Consume(Token::COMMA);
1479 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001480 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001481
1482 // Declare variable.
1483 // Note that we *always* must treat the initial value via a separate init
1484 // assignment for variables and constants because the value must be assigned
1485 // when the variable is encountered in the source. But the variable/constant
1486 // is declared (and set to 'undefined') upon entering the function within
1487 // which the variable or constant is declared. Only function variables have
1488 // an initial value in the declaration (because they are initialized upon
1489 // entering the function).
1490 //
1491 // If we have a const declaration, in an inner scope, the proxy is always
1492 // bound to the declared variable (independent of possibly surrounding with
1493 // statements).
1494 last_var = Declare(name, mode, NULL,
1495 is_const /* always bound for CONST! */,
1496 CHECK_OK);
1497 nvars++;
1498
1499 // Parse initialization expression if present and/or needed. A
1500 // declaration of the form:
1501 //
1502 // var v = x;
1503 //
1504 // is syntactic sugar for:
1505 //
1506 // var v; v = x;
1507 //
1508 // In particular, we need to re-lookup 'v' as it may be a
1509 // different 'v' than the 'v' in the declaration (if we are inside
1510 // a 'with' statement that makes a object property with name 'v'
1511 // visible).
1512 //
1513 // However, note that const declarations are different! A const
1514 // declaration of the form:
1515 //
1516 // const c = x;
1517 //
1518 // is *not* syntactic sugar for:
1519 //
1520 // const c; c = x;
1521 //
1522 // The "variable" c initialized to x is the same as the declared
1523 // one - there is no re-lookup (see the last parameter of the
1524 // Declare() call above).
1525
1526 Expression* value = NULL;
1527 int position = -1;
1528 if (peek() == Token::ASSIGN) {
1529 Expect(Token::ASSIGN, CHECK_OK);
1530 position = scanner().location().beg_pos;
1531 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001532 // Don't infer if it is "a = function(){...}();"-like expression.
1533 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer();
Steve Blocka7e24c12009-10-30 11:49:00 +00001534 }
1535
1536 // Make sure that 'const c' actually initializes 'c' to undefined
1537 // even though it seems like a stupid thing to do.
1538 if (value == NULL && is_const) {
1539 value = GetLiteralUndefined();
1540 }
1541
1542 // Global variable declarations must be compiled in a specific
1543 // way. When the script containing the global variable declaration
1544 // is entered, the global variable must be declared, so that if it
1545 // doesn't exist (not even in a prototype of the global object) it
1546 // gets created with an initial undefined value. This is handled
1547 // by the declarations part of the function representing the
1548 // top-level global code; see Runtime::DeclareGlobalVariable. If
1549 // it already exists (in the object or in a prototype), it is
1550 // *not* touched until the variable declaration statement is
1551 // executed.
1552 //
1553 // Executing the variable declaration statement will always
1554 // guarantee to give the global object a "local" variable; a
1555 // variable defined in the global object and not in any
1556 // prototype. This way, global variable declarations can shadow
1557 // properties in the prototype chain, but only after the variable
1558 // declaration statement has been executed. This is important in
1559 // browsers where the global object (window) has lots of
1560 // properties defined in prototype objects.
1561
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001562 if (top_scope_->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001563 // Compute the arguments for the runtime call.
1564 ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
1565 // Be careful not to assign a value to the global variable if
1566 // we're in a with. The initialization value should not
1567 // necessarily be stored in the global object in that case,
1568 // which is why we need to generate a separate assignment node.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001569 arguments->Add(new Literal(name)); // we have at least 1 parameter
Steve Blocka7e24c12009-10-30 11:49:00 +00001570 if (is_const || (value != NULL && !inside_with())) {
1571 arguments->Add(value);
1572 value = NULL; // zap the value to avoid the unnecessary assignment
1573 }
1574 // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
1575 // and add it to the initialization statement block. Note that
1576 // this function does different things depending on if we have
1577 // 1 or 2 parameters.
1578 CallRuntime* initialize;
1579 if (is_const) {
1580 initialize =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001581 new CallRuntime(
Steve Blocka7e24c12009-10-30 11:49:00 +00001582 Factory::InitializeConstGlobal_symbol(),
1583 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001584 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001585 } else {
1586 initialize =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001587 new CallRuntime(
Steve Blocka7e24c12009-10-30 11:49:00 +00001588 Factory::InitializeVarGlobal_symbol(),
1589 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001590 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001591 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001592 block->AddStatement(new ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001593 }
1594
1595 // Add an assignment node to the initialization statement block if
1596 // we still have a pending initialization value. We must distinguish
1597 // between variables and constants: Variable initializations are simply
1598 // assignments (with all the consequences if they are inside a 'with'
1599 // statement - they may change a 'with' object property). Constant
1600 // initializations always assign to the declared constant which is
1601 // always at the function scope level. This is only relevant for
1602 // dynamically looked-up variables and constants (the start context
1603 // for constant lookups is always the function context, while it is
1604 // the top context for variables). Sigh...
1605 if (value != NULL) {
1606 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001607 Assignment* assignment = new Assignment(op, last_var, value, position);
1608 if (block) block->AddStatement(new ExpressionStatement(assignment));
Steve Blocka7e24c12009-10-30 11:49:00 +00001609 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001610
1611 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001612 } while (peek() == Token::COMMA);
1613
1614 if (!is_const && nvars == 1) {
1615 // We have a single, non-const variable.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001616 ASSERT(last_var != NULL);
1617 *var = last_var;
Steve Blocka7e24c12009-10-30 11:49:00 +00001618 }
1619
1620 return block;
1621}
1622
1623
1624static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1625 ASSERT(!label.is_null());
1626 if (labels != NULL)
1627 for (int i = labels->length(); i-- > 0; )
1628 if (labels->at(i).is_identical_to(label))
1629 return true;
1630
1631 return false;
1632}
1633
1634
1635Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1636 bool* ok) {
1637 // ExpressionStatement | LabelledStatement ::
1638 // Expression ';'
1639 // Identifier ':' Statement
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001640 bool starts_with_idenfifier = (peek() == Token::IDENTIFIER);
Steve Blocka7e24c12009-10-30 11:49:00 +00001641 Expression* expr = ParseExpression(true, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001642 if (peek() == Token::COLON && starts_with_idenfifier && expr &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001643 expr->AsVariableProxy() != NULL &&
1644 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001645 // Expression is a single identifier, and not, e.g., a parenthesized
1646 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001647 VariableProxy* var = expr->AsVariableProxy();
1648 Handle<String> label = var->name();
1649 // TODO(1240780): We don't check for redeclaration of labels
1650 // during preparsing since keeping track of the set of active
1651 // labels requires nontrivial changes to the way scopes are
1652 // structured. However, these are probably changes we want to
1653 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001654 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1655 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1656 const char* elms[2] = { "Label", *c_string };
1657 Vector<const char*> args(elms, 2);
1658 ReportMessage("redeclaration", args);
1659 *ok = false;
1660 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001661 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001662 if (labels == NULL) labels = new ZoneStringList(4);
1663 labels->Add(label);
1664 // Remove the "ghost" variable that turned out to be a label
1665 // from the top scope. This way, we don't try to resolve it
1666 // during the scope processing.
1667 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001668 Expect(Token::COLON, CHECK_OK);
1669 return ParseStatement(labels, ok);
1670 }
1671
1672 // Parsed expression statement.
1673 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001674 return new ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001675}
1676
1677
1678IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1679 // IfStatement ::
1680 // 'if' '(' Expression ')' Statement ('else' Statement)?
1681
1682 Expect(Token::IF, CHECK_OK);
1683 Expect(Token::LPAREN, CHECK_OK);
1684 Expression* condition = ParseExpression(true, CHECK_OK);
1685 Expect(Token::RPAREN, CHECK_OK);
1686 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1687 Statement* else_statement = NULL;
1688 if (peek() == Token::ELSE) {
1689 Next();
1690 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001691 } else {
1692 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001693 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001694 return new IfStatement(condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001695}
1696
1697
1698Statement* Parser::ParseContinueStatement(bool* ok) {
1699 // ContinueStatement ::
1700 // 'continue' Identifier? ';'
1701
1702 Expect(Token::CONTINUE, CHECK_OK);
1703 Handle<String> label = Handle<String>::null();
1704 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001705 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001706 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1707 label = ParseIdentifier(CHECK_OK);
1708 }
1709 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001710 target = LookupContinueTarget(label, CHECK_OK);
1711 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001712 // Illegal continue statement.
1713 const char* message = "illegal_continue";
1714 Vector<Handle<String> > args;
1715 if (!label.is_null()) {
1716 message = "unknown_label";
1717 args = Vector<Handle<String> >(&label, 1);
1718 }
1719 ReportMessageAt(scanner().location(), message, args);
1720 *ok = false;
1721 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001722 }
1723 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001724 return new ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001725}
1726
1727
1728Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1729 // BreakStatement ::
1730 // 'break' Identifier? ';'
1731
1732 Expect(Token::BREAK, CHECK_OK);
1733 Handle<String> label;
1734 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001735 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001736 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1737 label = ParseIdentifier(CHECK_OK);
1738 }
1739 // Parse labeled break statements that target themselves into
1740 // empty statements, e.g. 'l1: l2: l3: break l2;'
1741 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001742 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001743 }
1744 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001745 target = LookupBreakTarget(label, CHECK_OK);
1746 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001747 // Illegal break statement.
1748 const char* message = "illegal_break";
1749 Vector<Handle<String> > args;
1750 if (!label.is_null()) {
1751 message = "unknown_label";
1752 args = Vector<Handle<String> >(&label, 1);
1753 }
1754 ReportMessageAt(scanner().location(), message, args);
1755 *ok = false;
1756 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001757 }
1758 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001759 return new BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001760}
1761
1762
1763Statement* Parser::ParseReturnStatement(bool* ok) {
1764 // ReturnStatement ::
1765 // 'return' Expression? ';'
1766
1767 // Consume the return token. It is necessary to do the before
1768 // reporting any errors on it, because of the way errors are
1769 // reported (underlining).
1770 Expect(Token::RETURN, CHECK_OK);
1771
1772 // An ECMAScript program is considered syntactically incorrect if it
1773 // contains a return statement that is not within the body of a
1774 // function. See ECMA-262, section 12.9, page 67.
1775 //
1776 // To be consistent with KJS we report the syntax error at runtime.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001777 if (!top_scope_->is_function_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001778 Handle<String> type = Factory::illegal_return_symbol();
1779 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001780 return new ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001781 }
1782
1783 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001784 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001785 tok == Token::SEMICOLON ||
1786 tok == Token::RBRACE ||
1787 tok == Token::EOS) {
1788 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001789 return new ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001790 }
1791
1792 Expression* expr = ParseExpression(true, CHECK_OK);
1793 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001794 return new ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001795}
1796
1797
1798Block* Parser::WithHelper(Expression* obj,
1799 ZoneStringList* labels,
1800 bool is_catch_block,
1801 bool* ok) {
1802 // Parse the statement and collect escaping labels.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001803 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001804 TargetCollector collector(target_list);
1805 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001806 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001807 with_nesting_level_++;
1808 top_scope_->RecordWithStatement();
1809 stat = ParseStatement(labels, CHECK_OK);
1810 with_nesting_level_--;
1811 }
1812 // Create resulting block with two statements.
1813 // 1: Evaluate the with expression.
1814 // 2: The try-finally block evaluating the body.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001815 Block* result = new Block(NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001816
1817 if (result != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001818 result->AddStatement(new WithEnterStatement(obj, is_catch_block));
Steve Blocka7e24c12009-10-30 11:49:00 +00001819
1820 // Create body block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001821 Block* body = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001822 body->AddStatement(stat);
1823
1824 // Create exit block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001825 Block* exit = new Block(NULL, 1, false);
1826 exit->AddStatement(new WithExitStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00001827
1828 // Return a try-finally statement.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001829 TryFinallyStatement* wrapper = new TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001830 wrapper->set_escaping_targets(collector.targets());
1831 result->AddStatement(wrapper);
1832 }
1833 return result;
1834}
1835
1836
1837Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
1838 // WithStatement ::
1839 // 'with' '(' Expression ')' Statement
1840
1841 Expect(Token::WITH, CHECK_OK);
1842 Expect(Token::LPAREN, CHECK_OK);
1843 Expression* expr = ParseExpression(true, CHECK_OK);
1844 Expect(Token::RPAREN, CHECK_OK);
1845
1846 return WithHelper(expr, labels, false, CHECK_OK);
1847}
1848
1849
1850CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1851 // CaseClause ::
1852 // 'case' Expression ':' Statement*
1853 // 'default' ':' Statement*
1854
1855 Expression* label = NULL; // NULL expression indicates default case
1856 if (peek() == Token::CASE) {
1857 Expect(Token::CASE, CHECK_OK);
1858 label = ParseExpression(true, CHECK_OK);
1859 } else {
1860 Expect(Token::DEFAULT, CHECK_OK);
1861 if (*default_seen_ptr) {
1862 ReportMessage("multiple_defaults_in_switch",
1863 Vector<const char*>::empty());
1864 *ok = false;
1865 return NULL;
1866 }
1867 *default_seen_ptr = true;
1868 }
1869 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001870 int pos = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001871 ZoneList<Statement*>* statements = new ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001872 while (peek() != Token::CASE &&
1873 peek() != Token::DEFAULT &&
1874 peek() != Token::RBRACE) {
1875 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001876 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001877 }
1878
Ben Murdochb0fe1622011-05-05 13:52:32 +01001879 return new CaseClause(label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001880}
1881
1882
1883SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
1884 bool* ok) {
1885 // SwitchStatement ::
1886 // 'switch' '(' Expression ')' '{' CaseClause* '}'
1887
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001888 SwitchStatement* statement = new SwitchStatement(labels);
1889 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001890
1891 Expect(Token::SWITCH, CHECK_OK);
1892 Expect(Token::LPAREN, CHECK_OK);
1893 Expression* tag = ParseExpression(true, CHECK_OK);
1894 Expect(Token::RPAREN, CHECK_OK);
1895
1896 bool default_seen = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001897 ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001898 Expect(Token::LBRACE, CHECK_OK);
1899 while (peek() != Token::RBRACE) {
1900 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001901 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00001902 }
1903 Expect(Token::RBRACE, CHECK_OK);
1904
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001905 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00001906 return statement;
1907}
1908
1909
1910Statement* Parser::ParseThrowStatement(bool* ok) {
1911 // ThrowStatement ::
1912 // 'throw' Expression ';'
1913
1914 Expect(Token::THROW, CHECK_OK);
1915 int pos = scanner().location().beg_pos;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001916 if (scanner().has_line_terminator_before_next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001917 ReportMessage("newline_after_throw", Vector<const char*>::empty());
1918 *ok = false;
1919 return NULL;
1920 }
1921 Expression* exception = ParseExpression(true, CHECK_OK);
1922 ExpectSemicolon(CHECK_OK);
1923
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001924 return new ExpressionStatement(new Throw(exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00001925}
1926
1927
1928TryStatement* Parser::ParseTryStatement(bool* ok) {
1929 // TryStatement ::
1930 // 'try' Block Catch
1931 // 'try' Block Finally
1932 // 'try' Block Catch Finally
1933 //
1934 // Catch ::
1935 // 'catch' '(' Identifier ')' Block
1936 //
1937 // Finally ::
1938 // 'finally' Block
1939
1940 Expect(Token::TRY, CHECK_OK);
1941
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001942 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001943 TargetCollector collector(target_list);
1944 Block* try_block;
1945
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001946 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001947 try_block = ParseBlock(NULL, CHECK_OK);
1948 }
1949
1950 Block* catch_block = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001951 Variable* catch_var = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001952 Block* finally_block = NULL;
1953
1954 Token::Value tok = peek();
1955 if (tok != Token::CATCH && tok != Token::FINALLY) {
1956 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
1957 *ok = false;
1958 return NULL;
1959 }
1960
1961 // If we can break out from the catch block and there is a finally block,
1962 // then we will need to collect jump targets from the catch block. Since
1963 // we don't know yet if there will be a finally block, we always collect
1964 // the jump targets.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001965 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001966 TargetCollector catch_collector(catch_target_list);
1967 bool has_catch = false;
1968 if (tok == Token::CATCH) {
1969 has_catch = true;
1970 Consume(Token::CATCH);
1971
1972 Expect(Token::LPAREN, CHECK_OK);
1973 Handle<String> name = ParseIdentifier(CHECK_OK);
1974 Expect(Token::RPAREN, CHECK_OK);
1975
1976 if (peek() == Token::LBRACE) {
1977 // Allocate a temporary for holding the finally state while
1978 // executing the finally block.
1979 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001980 Literal* name_literal = new Literal(name);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001981 VariableProxy* catch_var_use = new VariableProxy(catch_var);
1982 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001983 { Target target(&this->target_stack_, &catch_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001984 catch_block = WithHelper(obj, NULL, true, CHECK_OK);
1985 }
1986 } else {
1987 Expect(Token::LBRACE, CHECK_OK);
1988 }
1989
1990 tok = peek();
1991 }
1992
1993 if (tok == Token::FINALLY || !has_catch) {
1994 Consume(Token::FINALLY);
1995 // Declare a variable for holding the finally state while
1996 // executing the finally block.
1997 finally_block = ParseBlock(NULL, CHECK_OK);
1998 }
1999
2000 // Simplify the AST nodes by converting:
2001 // 'try { } catch { } finally { }'
2002 // to:
2003 // 'try { try { } catch { } } finally { }'
2004
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002005 if (catch_block != NULL && finally_block != NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002006 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
Steve Block3ce2e202009-11-05 08:53:23 +00002007 TryCatchStatement* statement =
Ben Murdochb0fe1622011-05-05 13:52:32 +01002008 new TryCatchStatement(try_block, catch_var_defn, catch_block);
Steve Blocka7e24c12009-10-30 11:49:00 +00002009 statement->set_escaping_targets(collector.targets());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002010 try_block = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002011 try_block->AddStatement(statement);
2012 catch_block = NULL;
2013 }
2014
2015 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002016 if (catch_block != NULL) {
2017 ASSERT(finally_block == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002018 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
2019 result = new TryCatchStatement(try_block, catch_var_defn, catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002020 result->set_escaping_targets(collector.targets());
2021 } else {
2022 ASSERT(finally_block != NULL);
2023 result = new TryFinallyStatement(try_block, finally_block);
2024 // Add the jump targets of the try block and the catch block.
2025 for (int i = 0; i < collector.targets()->length(); i++) {
2026 catch_collector.AddTarget(collector.targets()->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002027 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002028 result->set_escaping_targets(catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002029 }
2030
2031 return result;
2032}
2033
2034
Steve Block3ce2e202009-11-05 08:53:23 +00002035DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2036 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002037 // DoStatement ::
2038 // 'do' Statement 'while' '(' Expression ')' ';'
2039
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002040 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002041 DoWhileStatement* loop = new DoWhileStatement(labels);
2042 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002043
2044 Expect(Token::DO, CHECK_OK);
2045 Statement* body = ParseStatement(NULL, CHECK_OK);
2046 Expect(Token::WHILE, CHECK_OK);
2047 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002048
2049 if (loop != NULL) {
2050 int position = scanner().location().beg_pos;
2051 loop->set_condition_position(position);
2052 }
2053
Steve Blocka7e24c12009-10-30 11:49:00 +00002054 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002055 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002056 Expect(Token::RPAREN, CHECK_OK);
2057
2058 // Allow do-statements to be terminated with and without
2059 // semi-colons. This allows code such as 'do;while(0)return' to
2060 // parse, which would not be the case if we had used the
2061 // ExpectSemicolon() functionality here.
2062 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2063
Steve Block3ce2e202009-11-05 08:53:23 +00002064 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002065 return loop;
2066}
2067
2068
Steve Block3ce2e202009-11-05 08:53:23 +00002069WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002070 // WhileStatement ::
2071 // 'while' '(' Expression ')' Statement
2072
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002073 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002074 WhileStatement* loop = new WhileStatement(labels);
2075 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002076
2077 Expect(Token::WHILE, CHECK_OK);
2078 Expect(Token::LPAREN, CHECK_OK);
2079 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002080 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002081 Expect(Token::RPAREN, CHECK_OK);
2082 Statement* body = ParseStatement(NULL, CHECK_OK);
2083
Steve Block3ce2e202009-11-05 08:53:23 +00002084 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002085 return loop;
2086}
2087
2088
2089Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2090 // ForStatement ::
2091 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2092
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002093 temp_scope_->AddLoop();
Steve Blocka7e24c12009-10-30 11:49:00 +00002094 Statement* init = NULL;
2095
2096 Expect(Token::FOR, CHECK_OK);
2097 Expect(Token::LPAREN, CHECK_OK);
2098 if (peek() != Token::SEMICOLON) {
2099 if (peek() == Token::VAR || peek() == Token::CONST) {
2100 Expression* each = NULL;
2101 Block* variable_statement =
2102 ParseVariableDeclarations(false, &each, CHECK_OK);
2103 if (peek() == Token::IN && each != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002104 ForInStatement* loop = new ForInStatement(labels);
2105 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002106
2107 Expect(Token::IN, CHECK_OK);
2108 Expression* enumerable = ParseExpression(true, CHECK_OK);
2109 Expect(Token::RPAREN, CHECK_OK);
2110
2111 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002112 loop->Initialize(each, enumerable, body);
2113 Block* result = new Block(NULL, 2, false);
2114 result->AddStatement(variable_statement);
2115 result->AddStatement(loop);
2116 // Parsed for-in loop w/ variable/const declaration.
2117 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002118 } else {
2119 init = variable_statement;
2120 }
2121
2122 } else {
2123 Expression* expression = ParseExpression(false, CHECK_OK);
2124 if (peek() == Token::IN) {
2125 // Signal a reference error if the expression is an invalid
2126 // left-hand side expression. We could report this as a syntax
2127 // error here but for compatibility with JSC we choose to report
2128 // the error at runtime.
2129 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2130 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
2131 expression = NewThrowReferenceError(type);
2132 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002133 ForInStatement* loop = new ForInStatement(labels);
2134 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002135
2136 Expect(Token::IN, CHECK_OK);
2137 Expression* enumerable = ParseExpression(true, CHECK_OK);
2138 Expect(Token::RPAREN, CHECK_OK);
2139
2140 Statement* body = ParseStatement(NULL, CHECK_OK);
2141 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002142 // Parsed for-in loop.
2143 return loop;
2144
2145 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002146 init = new ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002147 }
2148 }
2149 }
2150
2151 // Standard 'for' loop
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002152 ForStatement* loop = new ForStatement(labels);
2153 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002154
2155 // Parsed initializer at this point.
2156 Expect(Token::SEMICOLON, CHECK_OK);
2157
2158 Expression* cond = NULL;
2159 if (peek() != Token::SEMICOLON) {
2160 cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002161 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002162 }
2163 Expect(Token::SEMICOLON, CHECK_OK);
2164
2165 Statement* next = NULL;
2166 if (peek() != Token::RPAREN) {
2167 Expression* exp = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002168 next = new ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002169 }
2170 Expect(Token::RPAREN, CHECK_OK);
2171
2172 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002173 if (loop) loop->Initialize(init, cond, next, body);
2174 return loop;
2175}
2176
2177
2178// Precedence = 1
2179Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2180 // Expression ::
2181 // AssignmentExpression
2182 // Expression ',' AssignmentExpression
2183
2184 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2185 while (peek() == Token::COMMA) {
2186 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002187 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002189 result = new BinaryOperation(Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002190 }
2191 return result;
2192}
2193
2194
2195// Precedence = 2
2196Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2197 // AssignmentExpression ::
2198 // ConditionalExpression
2199 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2200
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002201 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002202 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2203
2204 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002205 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002206 // Parsed conditional expression only (no assignment).
2207 return expression;
2208 }
2209
2210 // Signal a reference error if the expression is an invalid left-hand
2211 // side expression. We could report this as a syntax error here but
2212 // for compatibility with JSC we choose to report the error at
2213 // runtime.
2214 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2215 Handle<String> type = Factory::invalid_lhs_in_assignment_symbol();
2216 expression = NewThrowReferenceError(type);
2217 }
2218
2219 Token::Value op = Next(); // Get assignment operator.
2220 int pos = scanner().location().beg_pos;
2221 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2222
2223 // TODO(1231235): We try to estimate the set of properties set by
2224 // constructors. We define a new property whenever there is an
2225 // assignment to a property of 'this'. We should probably only add
2226 // properties if we haven't seen them before. Otherwise we'll
2227 // probably overestimate the number of properties.
2228 Property* property = expression ? expression->AsProperty() : NULL;
2229 if (op == Token::ASSIGN &&
2230 property != NULL &&
2231 property->obj()->AsVariableProxy() != NULL &&
2232 property->obj()->AsVariableProxy()->is_this()) {
2233 temp_scope_->AddProperty();
2234 }
2235
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002236 // If we assign a function literal to a property we pretenure the
2237 // literal so it can be added as a constant function property.
2238 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2239 right->AsFunctionLiteral()->set_pretenure(true);
2240 }
2241
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002242 if (fni_ != NULL) {
2243 // Check if the right hand side is a call to avoid inferring a
2244 // name if we're dealing with "a = function(){...}();"-like
2245 // expression.
2246 if ((op == Token::INIT_VAR
2247 || op == Token::INIT_CONST
2248 || op == Token::ASSIGN)
2249 && (right->AsCall() == NULL)) {
2250 fni_->Infer();
2251 }
2252 fni_->Leave();
2253 }
2254
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002255 return new Assignment(op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002256}
2257
2258
2259// Precedence = 3
2260Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2261 // ConditionalExpression ::
2262 // LogicalOrExpression
2263 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2264
2265 // We start using the binary expression parser for prec >= 4 only!
2266 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2267 if (peek() != Token::CONDITIONAL) return expression;
2268 Consume(Token::CONDITIONAL);
2269 // In parsing the first assignment expression in conditional
2270 // expressions we always accept the 'in' keyword; see ECMA-262,
2271 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002272 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002273 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2274 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002275 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002276 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002277 return new Conditional(expression, left, right,
2278 left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002279}
2280
2281
2282static int Precedence(Token::Value tok, bool accept_IN) {
2283 if (tok == Token::IN && !accept_IN)
2284 return 0; // 0 precedence will terminate binary expression parsing
2285
2286 return Token::Precedence(tok);
2287}
2288
2289
2290// Precedence >= 4
2291Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2292 ASSERT(prec >= 4);
2293 Expression* x = ParseUnaryExpression(CHECK_OK);
2294 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2295 // prec1 >= 4
2296 while (Precedence(peek(), accept_IN) == prec1) {
2297 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002298 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002299 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2300
2301 // Compute some expressions involving only number literals.
2302 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2303 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2304 double x_val = x->AsLiteral()->handle()->Number();
2305 double y_val = y->AsLiteral()->handle()->Number();
2306
2307 switch (op) {
2308 case Token::ADD:
2309 x = NewNumberLiteral(x_val + y_val);
2310 continue;
2311 case Token::SUB:
2312 x = NewNumberLiteral(x_val - y_val);
2313 continue;
2314 case Token::MUL:
2315 x = NewNumberLiteral(x_val * y_val);
2316 continue;
2317 case Token::DIV:
2318 x = NewNumberLiteral(x_val / y_val);
2319 continue;
2320 case Token::BIT_OR:
2321 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2322 continue;
2323 case Token::BIT_AND:
2324 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2325 continue;
2326 case Token::BIT_XOR:
2327 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2328 continue;
2329 case Token::SHL: {
2330 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2331 x = NewNumberLiteral(value);
2332 continue;
2333 }
2334 case Token::SHR: {
2335 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2336 uint32_t value = DoubleToUint32(x_val) >> shift;
2337 x = NewNumberLiteral(value);
2338 continue;
2339 }
2340 case Token::SAR: {
2341 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2342 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2343 x = NewNumberLiteral(value);
2344 continue;
2345 }
2346 default:
2347 break;
2348 }
2349 }
2350
Steve Blocka7e24c12009-10-30 11:49:00 +00002351 // For now we distinguish between comparisons and other binary
2352 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002353 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002354 if (Token::IsCompareOp(op)) {
2355 // We have a comparison.
2356 Token::Value cmp = op;
2357 switch (op) {
2358 case Token::NE: cmp = Token::EQ; break;
2359 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2360 default: break;
2361 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002362 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002363 if (cmp != op) {
2364 // The comparison was negated - add a NOT.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002365 x = new UnaryOperation(Token::NOT, x);
Steve Blocka7e24c12009-10-30 11:49:00 +00002366 }
2367
2368 } else {
2369 // We have a "normal" binary operation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002370 x = new BinaryOperation(op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002371 }
2372 }
2373 }
2374 return x;
2375}
2376
2377
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002378Expression* Parser::NewCompareNode(Token::Value op,
2379 Expression* x,
2380 Expression* y,
2381 int position) {
2382 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002383 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002384 bool is_strict = (op == Token::EQ_STRICT);
2385 Literal* x_literal = x->AsLiteral();
2386 if (x_literal != NULL && x_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002387 return new CompareToNull(is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002388 }
2389
2390 Literal* y_literal = y->AsLiteral();
2391 if (y_literal != NULL && y_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002392 return new CompareToNull(is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002393 }
2394 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002395 return new CompareOperation(op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002396}
2397
2398
Steve Blocka7e24c12009-10-30 11:49:00 +00002399Expression* Parser::ParseUnaryExpression(bool* ok) {
2400 // UnaryExpression ::
2401 // PostfixExpression
2402 // 'delete' UnaryExpression
2403 // 'void' UnaryExpression
2404 // 'typeof' UnaryExpression
2405 // '++' UnaryExpression
2406 // '--' UnaryExpression
2407 // '+' UnaryExpression
2408 // '-' UnaryExpression
2409 // '~' UnaryExpression
2410 // '!' UnaryExpression
2411
2412 Token::Value op = peek();
2413 if (Token::IsUnaryOp(op)) {
2414 op = Next();
2415 Expression* expression = ParseUnaryExpression(CHECK_OK);
2416
2417 // Compute some expressions involving only number literals.
2418 if (expression != NULL && expression->AsLiteral() &&
2419 expression->AsLiteral()->handle()->IsNumber()) {
2420 double value = expression->AsLiteral()->handle()->Number();
2421 switch (op) {
2422 case Token::ADD:
2423 return expression;
2424 case Token::SUB:
2425 return NewNumberLiteral(-value);
2426 case Token::BIT_NOT:
2427 return NewNumberLiteral(~DoubleToInt32(value));
2428 default: break;
2429 }
2430 }
2431
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002432 return new UnaryOperation(op, expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002433
2434 } else if (Token::IsCountOp(op)) {
2435 op = Next();
2436 Expression* expression = ParseUnaryExpression(CHECK_OK);
2437 // Signal a reference error if the expression is an invalid
2438 // left-hand side expression. We could report this as a syntax
2439 // error here but for compatibility with JSC we choose to report the
2440 // error at runtime.
2441 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2442 Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
2443 expression = NewThrowReferenceError(type);
2444 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002445 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002446 IncrementOperation* increment = new IncrementOperation(op, expression);
2447 return new CountOperation(true /* prefix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002448
2449 } else {
2450 return ParsePostfixExpression(ok);
2451 }
2452}
2453
2454
2455Expression* Parser::ParsePostfixExpression(bool* ok) {
2456 // PostfixExpression ::
2457 // LeftHandSideExpression ('++' | '--')?
2458
2459 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002460 if (!scanner().has_line_terminator_before_next() &&
2461 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002462 // Signal a reference error if the expression is an invalid
2463 // left-hand side expression. We could report this as a syntax
2464 // error here but for compatibility with JSC we choose to report the
2465 // error at runtime.
2466 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2467 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
2468 expression = NewThrowReferenceError(type);
2469 }
2470 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002471 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002472 IncrementOperation* increment = new IncrementOperation(next, expression);
2473 expression = new CountOperation(false /* postfix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002474 }
2475 return expression;
2476}
2477
2478
2479Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2480 // LeftHandSideExpression ::
2481 // (NewExpression | MemberExpression) ...
2482
2483 Expression* result;
2484 if (peek() == Token::NEW) {
2485 result = ParseNewExpression(CHECK_OK);
2486 } else {
2487 result = ParseMemberExpression(CHECK_OK);
2488 }
2489
2490 while (true) {
2491 switch (peek()) {
2492 case Token::LBRACK: {
2493 Consume(Token::LBRACK);
2494 int pos = scanner().location().beg_pos;
2495 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002496 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002497 Expect(Token::RBRACK, CHECK_OK);
2498 break;
2499 }
2500
2501 case Token::LPAREN: {
2502 int pos = scanner().location().beg_pos;
2503 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2504
2505 // Keep track of eval() calls since they disable all local variable
2506 // optimizations.
2507 // The calls that need special treatment are the
2508 // direct (i.e. not aliased) eval calls. These calls are all of the
2509 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002510 // declared in the current scope chain.
2511 // These calls are marked as potentially direct eval calls. Whether
2512 // they are actually direct calls to eval is determined at run time.
2513 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2514 // in the local scope chain. It only matters that it's called "eval",
2515 // is called without a receiver and it refers to the original eval
2516 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002517 VariableProxy* callee = result->AsVariableProxy();
2518 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
2519 Handle<String> name = callee->name();
2520 Variable* var = top_scope_->Lookup(name);
2521 if (var == NULL) {
2522 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002523 }
2524 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002525 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002526 break;
2527 }
2528
2529 case Token::PERIOD: {
2530 Consume(Token::PERIOD);
2531 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002532 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002533 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002534 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002535 break;
2536 }
2537
2538 default:
2539 return result;
2540 }
2541 }
2542}
2543
2544
Steve Blocka7e24c12009-10-30 11:49:00 +00002545Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2546 // NewExpression ::
2547 // ('new')+ MemberExpression
2548
2549 // The grammar for new expressions is pretty warped. The keyword
2550 // 'new' can either be a part of the new expression (where it isn't
2551 // followed by an argument list) or a part of the member expression,
2552 // where it must be followed by an argument list. To accommodate
2553 // this, we parse the 'new' keywords greedily and keep track of how
2554 // many we have parsed. This information is then passed on to the
2555 // member expression parser, which is only allowed to match argument
2556 // lists as long as it has 'new' prefixes left
2557 Expect(Token::NEW, CHECK_OK);
2558 PositionStack::Element pos(stack, scanner().location().beg_pos);
2559
2560 Expression* result;
2561 if (peek() == Token::NEW) {
2562 result = ParseNewPrefix(stack, CHECK_OK);
2563 } else {
2564 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2565 }
2566
2567 if (!stack->is_empty()) {
2568 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002569 result = new CallNew(result, new ZoneList<Expression*>(0), last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002570 }
2571 return result;
2572}
2573
2574
2575Expression* Parser::ParseNewExpression(bool* ok) {
2576 PositionStack stack(ok);
2577 return ParseNewPrefix(&stack, ok);
2578}
2579
2580
2581Expression* Parser::ParseMemberExpression(bool* ok) {
2582 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2583}
2584
2585
2586Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2587 bool* ok) {
2588 // MemberExpression ::
2589 // (PrimaryExpression | FunctionLiteral)
2590 // ('[' Expression ']' | '.' Identifier | Arguments)*
2591
2592 // Parse the initial primary or function expression.
2593 Expression* result = NULL;
2594 if (peek() == Token::FUNCTION) {
2595 Expect(Token::FUNCTION, CHECK_OK);
2596 int function_token_position = scanner().location().beg_pos;
2597 Handle<String> name;
2598 if (peek() == Token::IDENTIFIER) name = ParseIdentifier(CHECK_OK);
2599 result = ParseFunctionLiteral(name, function_token_position,
2600 NESTED, CHECK_OK);
2601 } else {
2602 result = ParsePrimaryExpression(CHECK_OK);
2603 }
2604
2605 while (true) {
2606 switch (peek()) {
2607 case Token::LBRACK: {
2608 Consume(Token::LBRACK);
2609 int pos = scanner().location().beg_pos;
2610 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002611 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002612 Expect(Token::RBRACK, CHECK_OK);
2613 break;
2614 }
2615 case Token::PERIOD: {
2616 Consume(Token::PERIOD);
2617 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002618 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002619 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002620 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002621 break;
2622 }
2623 case Token::LPAREN: {
2624 if ((stack == NULL) || stack->is_empty()) return result;
2625 // Consume one of the new prefixes (already parsed).
2626 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2627 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002628 result = new CallNew(result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002629 break;
2630 }
2631 default:
2632 return result;
2633 }
2634 }
2635}
2636
2637
2638DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2639 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2640 // contexts this is used as a statement which invokes the debugger as i a
2641 // break point is present.
2642 // DebuggerStatement ::
2643 // 'debugger' ';'
2644
2645 Expect(Token::DEBUGGER, CHECK_OK);
2646 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002647 return new DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002648}
2649
2650
2651void Parser::ReportUnexpectedToken(Token::Value token) {
2652 // We don't report stack overflows here, to avoid increasing the
2653 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002654 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002655 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002656 // Four of the tokens are treated specially
2657 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002658 case Token::EOS:
2659 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2660 case Token::NUMBER:
2661 return ReportMessage("unexpected_token_number",
2662 Vector<const char*>::empty());
2663 case Token::STRING:
2664 return ReportMessage("unexpected_token_string",
2665 Vector<const char*>::empty());
2666 case Token::IDENTIFIER:
2667 return ReportMessage("unexpected_token_identifier",
2668 Vector<const char*>::empty());
2669 default:
2670 const char* name = Token::String(token);
2671 ASSERT(name != NULL);
2672 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002673 }
2674}
2675
2676
Leon Clarkeac952652010-07-15 11:15:24 +01002677void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2678 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2679 const char* element[1] = { *name_string };
2680 ReportMessage("invalid_preparser_data",
2681 Vector<const char*>(element, 1));
2682 *ok = false;
2683}
2684
2685
Steve Blocka7e24c12009-10-30 11:49:00 +00002686Expression* Parser::ParsePrimaryExpression(bool* ok) {
2687 // PrimaryExpression ::
2688 // 'this'
2689 // 'null'
2690 // 'true'
2691 // 'false'
2692 // Identifier
2693 // Number
2694 // String
2695 // ArrayLiteral
2696 // ObjectLiteral
2697 // RegExpLiteral
2698 // '(' Expression ')'
2699
2700 Expression* result = NULL;
2701 switch (peek()) {
2702 case Token::THIS: {
2703 Consume(Token::THIS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002704 VariableProxy* recv = top_scope_->receiver();
2705 result = recv;
Steve Blocka7e24c12009-10-30 11:49:00 +00002706 break;
2707 }
2708
2709 case Token::NULL_LITERAL:
2710 Consume(Token::NULL_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002711 result = new Literal(Factory::null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002712 break;
2713
2714 case Token::TRUE_LITERAL:
2715 Consume(Token::TRUE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002716 result = new Literal(Factory::true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002717 break;
2718
2719 case Token::FALSE_LITERAL:
2720 Consume(Token::FALSE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002721 result = new Literal(Factory::false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002722 break;
2723
2724 case Token::IDENTIFIER: {
2725 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002726 if (fni_ != NULL) fni_->PushVariableName(name);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002727 result = top_scope_->NewUnresolved(name, inside_with());
Steve Blocka7e24c12009-10-30 11:49:00 +00002728 break;
2729 }
2730
2731 case Token::NUMBER: {
2732 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01002733 ASSERT(scanner().is_literal_ascii());
2734 double value = StringToDouble(scanner().literal_ascii_string(),
2735 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002736 result = NewNumberLiteral(value);
2737 break;
2738 }
2739
2740 case Token::STRING: {
2741 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01002742 Handle<String> symbol = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002743 result = new Literal(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002744 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002745 break;
2746 }
2747
2748 case Token::ASSIGN_DIV:
2749 result = ParseRegExpLiteral(true, CHECK_OK);
2750 break;
2751
2752 case Token::DIV:
2753 result = ParseRegExpLiteral(false, CHECK_OK);
2754 break;
2755
2756 case Token::LBRACK:
2757 result = ParseArrayLiteral(CHECK_OK);
2758 break;
2759
2760 case Token::LBRACE:
2761 result = ParseObjectLiteral(CHECK_OK);
2762 break;
2763
2764 case Token::LPAREN:
2765 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002766 // Heuristically try to detect immediately called functions before
2767 // seeing the call parentheses.
2768 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00002769 result = ParseExpression(true, CHECK_OK);
2770 Expect(Token::RPAREN, CHECK_OK);
2771 break;
2772
2773 case Token::MOD:
2774 if (allow_natives_syntax_ || extension_ != NULL) {
2775 result = ParseV8Intrinsic(CHECK_OK);
2776 break;
2777 }
2778 // If we're not allowing special syntax we fall-through to the
2779 // default case.
2780
2781 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01002782 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00002783 ReportUnexpectedToken(tok);
2784 *ok = false;
2785 return NULL;
2786 }
2787 }
2788
2789 return result;
2790}
2791
2792
Leon Clarke4515c472010-02-03 11:58:03 +00002793void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
2794 Handle<FixedArray> literals,
2795 bool* is_simple,
2796 int* depth) {
2797 // Fill in the literals.
2798 // Accumulate output values in local variables.
2799 bool is_simple_acc = true;
2800 int depth_acc = 1;
2801 for (int i = 0; i < values->length(); i++) {
2802 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
2803 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2804 depth_acc = m_literal->depth() + 1;
2805 }
2806 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
2807 if (boilerplate_value->IsUndefined()) {
2808 literals->set_the_hole(i);
2809 is_simple_acc = false;
2810 } else {
2811 literals->set(i, *boilerplate_value);
2812 }
2813 }
2814
2815 *is_simple = is_simple_acc;
2816 *depth = depth_acc;
2817}
2818
2819
Steve Blocka7e24c12009-10-30 11:49:00 +00002820Expression* Parser::ParseArrayLiteral(bool* ok) {
2821 // ArrayLiteral ::
2822 // '[' Expression? (',' Expression?)* ']'
2823
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002824 ZoneList<Expression*>* values = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002825 Expect(Token::LBRACK, CHECK_OK);
2826 while (peek() != Token::RBRACK) {
2827 Expression* elem;
2828 if (peek() == Token::COMMA) {
2829 elem = GetLiteralTheHole();
2830 } else {
2831 elem = ParseAssignmentExpression(true, CHECK_OK);
2832 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002833 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00002834 if (peek() != Token::RBRACK) {
2835 Expect(Token::COMMA, CHECK_OK);
2836 }
2837 }
2838 Expect(Token::RBRACK, CHECK_OK);
2839
2840 // Update the scope information before the pre-parsing bailout.
Steve Blocka7e24c12009-10-30 11:49:00 +00002841 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
2842
Steve Blocka7e24c12009-10-30 11:49:00 +00002843 // Allocate a fixed array with all the literals.
2844 Handle<FixedArray> literals =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002845 Factory::NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002846
2847 // Fill in the literals.
2848 bool is_simple = true;
2849 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002850 for (int i = 0, n = values->length(); i < n; i++) {
2851 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00002852 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
2853 depth = m_literal->depth() + 1;
2854 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002855 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002856 if (boilerplate_value->IsUndefined()) {
2857 literals->set_the_hole(i);
2858 is_simple = false;
2859 } else {
2860 literals->set(i, *boilerplate_value);
2861 }
2862 }
2863
Iain Merrick75681382010-08-19 15:07:18 +01002864 // Simple and shallow arrays can be lazily copied, we transform the
2865 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002866 if (is_simple && depth == 1 && values->length() > 0) {
Iain Merrick75681382010-08-19 15:07:18 +01002867 literals->set_map(Heap::fixed_cow_array_map());
2868 }
2869
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002870 return new ArrayLiteral(literals, values,
2871 literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00002872}
2873
2874
2875bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
2876 return property != NULL &&
2877 property->kind() != ObjectLiteral::Property::PROTOTYPE;
2878}
2879
2880
2881bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002882 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002883 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
2884 return lit != NULL && lit->is_simple();
2885}
2886
Iain Merrick75681382010-08-19 15:07:18 +01002887
2888bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
2889 Expression* value) {
2890 // If value is a literal the property value is already set in the
2891 // boilerplate object.
2892 if (value->AsLiteral() != NULL) return false;
2893 // If value is a materialized literal the property value is already set
2894 // in the boilerplate object if it is simple.
2895 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
2896 return true;
2897}
2898
2899
Steve Blocka7e24c12009-10-30 11:49:00 +00002900Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
2901 ASSERT(IsCompileTimeValue(expression));
2902 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
2903 ObjectLiteral* object_literal = expression->AsObjectLiteral();
2904 if (object_literal != NULL) {
2905 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01002906 if (object_literal->fast_elements()) {
2907 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
2908 } else {
2909 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
2910 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002911 result->set(kElementsSlot, *object_literal->constant_properties());
2912 } else {
2913 ArrayLiteral* array_literal = expression->AsArrayLiteral();
2914 ASSERT(array_literal != NULL && array_literal->is_simple());
2915 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00002916 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00002917 }
2918 return result;
2919}
2920
2921
2922CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
2923 Smi* type_value = Smi::cast(value->get(kTypeSlot));
2924 return static_cast<Type>(type_value->value());
2925}
2926
2927
2928Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
2929 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
2930}
2931
2932
2933Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
2934 if (expression->AsLiteral() != NULL) {
2935 return expression->AsLiteral()->handle();
2936 }
2937 if (CompileTimeValue::IsCompileTimeValue(expression)) {
2938 return CompileTimeValue::GetValue(expression);
2939 }
2940 return Factory::undefined_value();
2941}
2942
2943
Leon Clarke4515c472010-02-03 11:58:03 +00002944void Parser::BuildObjectLiteralConstantProperties(
2945 ZoneList<ObjectLiteral::Property*>* properties,
2946 Handle<FixedArray> constant_properties,
2947 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01002948 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00002949 int* depth) {
2950 int position = 0;
2951 // Accumulate the value in local variables and store it at the end.
2952 bool is_simple_acc = true;
2953 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01002954 uint32_t max_element_index = 0;
2955 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00002956 for (int i = 0; i < properties->length(); i++) {
2957 ObjectLiteral::Property* property = properties->at(i);
2958 if (!IsBoilerplateProperty(property)) {
2959 is_simple_acc = false;
2960 continue;
2961 }
2962 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
2963 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2964 depth_acc = m_literal->depth() + 1;
2965 }
2966
2967 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
2968 // value for COMPUTED properties, the real value is filled in at
2969 // runtime. The enumeration order is maintained.
2970 Handle<Object> key = property->key()->handle();
2971 Handle<Object> value = GetBoilerplateValue(property->value());
2972 is_simple_acc = is_simple_acc && !value->IsUndefined();
2973
Steve Block6ded16b2010-05-10 14:33:55 +01002974 // Keep track of the number of elements in the object literal and
2975 // the largest element index. If the largest element index is
2976 // much larger than the number of elements, creating an object
2977 // literal with fast elements will be a waste of space.
2978 uint32_t element_index = 0;
2979 if (key->IsString()
2980 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
2981 && element_index > max_element_index) {
2982 max_element_index = element_index;
2983 elements++;
2984 } else if (key->IsSmi()) {
2985 int key_value = Smi::cast(*key)->value();
2986 if (key_value > 0
2987 && static_cast<uint32_t>(key_value) > max_element_index) {
2988 max_element_index = key_value;
2989 }
2990 elements++;
2991 }
2992
Leon Clarke4515c472010-02-03 11:58:03 +00002993 // Add name, value pair to the fixed array.
2994 constant_properties->set(position++, *key);
2995 constant_properties->set(position++, *value);
2996 }
Steve Block6ded16b2010-05-10 14:33:55 +01002997 *fast_elements =
2998 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00002999 *is_simple = is_simple_acc;
3000 *depth = depth_acc;
3001}
3002
3003
Ben Murdochbb769b22010-08-11 14:56:33 +01003004ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3005 bool* ok) {
3006 // Special handling of getter and setter syntax:
3007 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3008 // We have already read the "get" or "set" keyword.
3009 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003010 bool is_keyword = Token::IsKeyword(next);
3011 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
3012 next == Token::STRING || is_keyword) {
3013 Handle<String> name;
3014 if (is_keyword) {
3015 name = Factory::LookupAsciiSymbol(Token::String(next));
3016 } else {
3017 name = GetSymbol(CHECK_OK);
3018 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003019 FunctionLiteral* value =
3020 ParseFunctionLiteral(name,
3021 RelocInfo::kNoPosition,
3022 DECLARATION,
3023 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003024 // Allow any number of parameters for compatiabilty with JSC.
3025 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003026 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003027 new ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003028 return property;
3029 } else {
3030 ReportUnexpectedToken(next);
3031 *ok = false;
3032 return NULL;
3033 }
3034}
3035
3036
Steve Blocka7e24c12009-10-30 11:49:00 +00003037Expression* Parser::ParseObjectLiteral(bool* ok) {
3038 // ObjectLiteral ::
3039 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003040 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3041 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003042 // )*[','] '}'
3043
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003044 ZoneList<ObjectLiteral::Property*>* properties =
3045 new ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003046 int number_of_boilerplate_properties = 0;
3047
3048 Expect(Token::LBRACE, CHECK_OK);
3049 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003050 if (fni_ != NULL) fni_->Enter();
3051
Steve Blocka7e24c12009-10-30 11:49:00 +00003052 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003053 Token::Value next = peek();
3054 switch (next) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003055 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003056 bool is_getter = false;
3057 bool is_setter = false;
3058 Handle<String> id =
3059 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003060 if (fni_ != NULL) fni_->PushLiteralName(id);
3061
Ben Murdochbb769b22010-08-11 14:56:33 +01003062 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003063 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003064 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3065 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003066 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003067 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003068 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003069 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003070
3071 if (fni_ != NULL) {
3072 fni_->Infer();
3073 fni_->Leave();
3074 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003075 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003076 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003077 // Failed to parse as get/set property, so it's just a property
3078 // called "get" or "set".
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003079 key = new Literal(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003080 break;
3081 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003082 case Token::STRING: {
3083 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003084 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003085 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003086 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003087 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003088 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003089 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003090 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003091 key = new Literal(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003092 break;
3093 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003094 case Token::NUMBER: {
3095 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003096 ASSERT(scanner().is_literal_ascii());
3097 double value = StringToDouble(scanner().literal_ascii_string(),
3098 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003099 key = NewNumberLiteral(value);
3100 break;
3101 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003102 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003103 if (Token::IsKeyword(next)) {
3104 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003105 Handle<String> string = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003106 key = new Literal(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003107 } else {
3108 // Unexpected token.
3109 Token::Value next = Next();
3110 ReportUnexpectedToken(next);
3111 *ok = false;
3112 return NULL;
3113 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003114 }
3115
3116 Expect(Token::COLON, CHECK_OK);
3117 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3118
3119 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003120 new ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003121
3122 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3123 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003124 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003125
3126 // TODO(1240767): Consider allowing trailing comma.
3127 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003128
3129 if (fni_ != NULL) {
3130 fni_->Infer();
3131 fni_->Leave();
3132 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003133 }
3134 Expect(Token::RBRACE, CHECK_OK);
3135 // Computation of literal_index must happen before pre parse bailout.
3136 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003137
3138 Handle<FixedArray> constant_properties =
3139 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003140
Steve Blocka7e24c12009-10-30 11:49:00 +00003141 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003142 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003143 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003144 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003145 constant_properties,
3146 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003147 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003148 &depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003149 return new ObjectLiteral(constant_properties,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003150 properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003151 literal_index,
3152 is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003153 fast_elements,
Steve Blocka7e24c12009-10-30 11:49:00 +00003154 depth);
3155}
3156
3157
3158Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003159 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003160 Next();
3161 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3162 *ok = false;
3163 return NULL;
3164 }
3165
3166 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
3167
Steve Block9fac8402011-05-12 15:51:54 +01003168 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003169 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003170 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003171 Next();
3172
3173 return new RegExpLiteral(js_pattern, js_flags, literal_index);
3174}
3175
3176
3177ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3178 // Arguments ::
3179 // '(' (AssignmentExpression)*[','] ')'
3180
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003181 ZoneList<Expression*>* result = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003182 Expect(Token::LPAREN, CHECK_OK);
3183 bool done = (peek() == Token::RPAREN);
3184 while (!done) {
3185 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003186 result->Add(argument);
Steve Blocka7e24c12009-10-30 11:49:00 +00003187 done = (peek() == Token::RPAREN);
3188 if (!done) Expect(Token::COMMA, CHECK_OK);
3189 }
3190 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003191 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003192}
3193
3194
3195FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
3196 int function_token_position,
3197 FunctionLiteralType type,
3198 bool* ok) {
3199 // Function ::
3200 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003201 bool is_named = !var_name.is_null();
3202
3203 // The name associated with this function. If it's a function expression,
3204 // this is the actual function name, otherwise this is the name of the
3205 // variable declared and initialized with the function (expression). In
3206 // that case, we don't have a function name (it's empty).
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003207 Handle<String> name = is_named ? var_name : Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003208 // The function name, if any.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003209 Handle<String> function_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003210 if (is_named && (type == EXPRESSION || type == NESTED)) {
3211 function_name = name;
3212 }
3213
3214 int num_parameters = 0;
3215 // Parse function body.
Ben Murdochf87a2032010-10-22 12:50:53 +01003216 { Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003217 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3218 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
3219 scope);
3220 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003221 top_scope_->SetScopeName(name);
3222
3223 // FormalParameterList ::
3224 // '(' (Identifier)*[','] ')'
3225 Expect(Token::LPAREN, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003226 int start_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003227 bool done = (peek() == Token::RPAREN);
3228 while (!done) {
3229 Handle<String> param_name = ParseIdentifier(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003230 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name,
3231 Variable::VAR));
3232 num_parameters++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003233 done = (peek() == Token::RPAREN);
3234 if (!done) Expect(Token::COMMA, CHECK_OK);
3235 }
3236 Expect(Token::RPAREN, CHECK_OK);
3237
3238 Expect(Token::LBRACE, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003239 ZoneList<Statement*>* body = new ZoneList<Statement*>(8);
Steve Blocka7e24c12009-10-30 11:49:00 +00003240
3241 // If we have a named function expression, we add a local variable
3242 // declaration to the body of the function with the name of the
3243 // function and let it refer to the function itself (closure).
3244 // NOTE: We create a proxy and resolve it here so that in the
3245 // future we can change the AST to only refer to VariableProxies
3246 // instead of Variables and Proxis as is the case now.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003247 if (!function_name.is_null() && function_name->length() > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003248 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3249 VariableProxy* fproxy =
3250 top_scope_->NewUnresolved(function_name, inside_with());
3251 fproxy->BindTo(fvar);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003252 body->Add(new ExpressionStatement(
3253 new Assignment(Token::INIT_CONST, fproxy,
3254 new ThisFunction(),
3255 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003256 }
3257
3258 // Determine if the function will be lazily compiled. The mode can
3259 // only be PARSE_LAZILY if the --lazy flag is true.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003260 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3261 top_scope_->outer_scope()->is_global_scope() &&
3262 top_scope_->HasTrivialOuterContext() &&
3263 !parenthesized_function_);
3264 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003265
Ben Murdochb0fe1622011-05-05 13:52:32 +01003266 int function_block_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003267 int materialized_literal_count;
3268 int expected_property_count;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003269 int end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003270 bool only_simple_this_property_assignments;
3271 Handle<FixedArray> this_property_assignments;
3272 if (is_lazily_compiled && pre_data() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003273 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003274 if (!entry.is_valid()) {
3275 ReportInvalidPreparseData(name, CHECK_OK);
3276 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003277 end_pos = entry.end_pos();
3278 if (end_pos <= function_block_pos) {
Leon Clarkeac952652010-07-15 11:15:24 +01003279 // End position greater than end of stream is safe, and hard to check.
3280 ReportInvalidPreparseData(name, CHECK_OK);
3281 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003282 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003283 // Seek to position just before terminal '}'.
3284 scanner().SeekForward(end_pos - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003285 materialized_literal_count = entry.literal_count();
3286 expected_property_count = entry.property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003287 only_simple_this_property_assignments = false;
3288 this_property_assignments = Factory::empty_fixed_array();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003289 Expect(Token::RBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003290 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003291 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3292
Steve Blocka7e24c12009-10-30 11:49:00 +00003293 materialized_literal_count = temp_scope.materialized_literal_count();
3294 expected_property_count = temp_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003295 only_simple_this_property_assignments =
3296 temp_scope.only_simple_this_property_assignments();
3297 this_property_assignments = temp_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003298
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003299 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003300 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003301 }
3302
3303 FunctionLiteral* function_literal =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003304 new FunctionLiteral(name,
Steve Blocka7e24c12009-10-30 11:49:00 +00003305 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003306 body,
Steve Blocka7e24c12009-10-30 11:49:00 +00003307 materialized_literal_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003308 expected_property_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003309 only_simple_this_property_assignments,
3310 this_property_assignments,
3311 num_parameters,
3312 start_pos,
3313 end_pos,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003314 function_name->length() > 0,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003315 temp_scope.ContainsLoops());
3316 function_literal->set_function_token_position(function_token_position);
Steve Block6ded16b2010-05-10 14:33:55 +01003317
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003318 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
Steve Blocka7e24c12009-10-30 11:49:00 +00003319 return function_literal;
3320 }
3321}
3322
3323
3324Expression* Parser::ParseV8Intrinsic(bool* ok) {
3325 // CallRuntime ::
3326 // '%' Identifier Arguments
3327
3328 Expect(Token::MOD, CHECK_OK);
3329 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003330 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003331
3332 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003333 // The extension structures are only accessible while parsing the
3334 // very first time not when reparsing because of lazy compilation.
3335 top_scope_->ForceEagerCompilation();
3336 }
3337
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003338 Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003339
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003340 // Check for built-in IS_VAR macro.
3341 if (function != NULL &&
3342 function->intrinsic_type == Runtime::RUNTIME &&
3343 function->function_id == Runtime::kIS_VAR) {
3344 // %IS_VAR(x) evaluates to x if x is a variable,
3345 // leads to a parse error otherwise. Could be implemented as an
3346 // inline function %_IS_VAR(x) to eliminate this special case.
3347 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3348 return args->at(0);
3349 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003350 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003351 *ok = false;
3352 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003353 }
3354 }
3355
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003356 // Check that the expected number of arguments are being passed.
3357 if (function != NULL &&
3358 function->nargs != -1 &&
3359 function->nargs != args->length()) {
3360 ReportMessage("illegal_access", Vector<const char*>::empty());
3361 *ok = false;
3362 return NULL;
3363 }
3364
3365 // We have a valid intrinsics call or a call to a builtin.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003366 return new CallRuntime(name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003367}
3368
3369
3370void Parser::Consume(Token::Value token) {
3371 Token::Value next = Next();
3372 USE(next);
3373 USE(token);
3374 ASSERT(next == token);
3375}
3376
3377
3378void Parser::Expect(Token::Value token, bool* ok) {
3379 Token::Value next = Next();
3380 if (next == token) return;
3381 ReportUnexpectedToken(next);
3382 *ok = false;
3383}
3384
3385
Leon Clarke4515c472010-02-03 11:58:03 +00003386bool Parser::Check(Token::Value token) {
3387 Token::Value next = peek();
3388 if (next == token) {
3389 Consume(next);
3390 return true;
3391 }
3392 return false;
3393}
3394
3395
Steve Blocka7e24c12009-10-30 11:49:00 +00003396void Parser::ExpectSemicolon(bool* ok) {
3397 // Check for automatic semicolon insertion according to
3398 // the rules given in ECMA-262, section 7.9, page 21.
3399 Token::Value tok = peek();
3400 if (tok == Token::SEMICOLON) {
3401 Next();
3402 return;
3403 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003404 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003405 tok == Token::RBRACE ||
3406 tok == Token::EOS) {
3407 return;
3408 }
3409 Expect(Token::SEMICOLON, ok);
3410}
3411
3412
3413Literal* Parser::GetLiteralUndefined() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003414 return new Literal(Factory::undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003415}
3416
3417
3418Literal* Parser::GetLiteralTheHole() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003419 return new Literal(Factory::the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003420}
3421
3422
3423Literal* Parser::GetLiteralNumber(double value) {
3424 return NewNumberLiteral(value);
3425}
3426
3427
3428Handle<String> Parser::ParseIdentifier(bool* ok) {
3429 Expect(Token::IDENTIFIER, ok);
3430 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003431 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003432}
3433
Ben Murdochbb769b22010-08-11 14:56:33 +01003434
3435Handle<String> Parser::ParseIdentifierName(bool* ok) {
3436 Token::Value next = Next();
3437 if (next != Token::IDENTIFIER && !Token::IsKeyword(next)) {
3438 ReportUnexpectedToken(next);
3439 *ok = false;
3440 return Handle<String>();
3441 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003442 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01003443}
3444
3445
Steve Blocka7e24c12009-10-30 11:49:00 +00003446// This function reads an identifier and determines whether or not it
3447// is 'get' or 'set'. The reason for not using ParseIdentifier and
3448// checking on the output is that this involves heap allocation which
3449// we can't do during preparsing.
3450Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3451 bool* is_set,
3452 bool* ok) {
3453 Expect(Token::IDENTIFIER, ok);
3454 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01003455 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
3456 const char* token = scanner().literal_ascii_string().start();
3457 *is_get = strncmp(token, "get", 3) == 0;
3458 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003459 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003460 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003461}
3462
3463
3464// ----------------------------------------------------------------------------
3465// Parser support
3466
3467
3468bool Parser::TargetStackContainsLabel(Handle<String> label) {
3469 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3470 BreakableStatement* stat = t->node()->AsBreakableStatement();
3471 if (stat != NULL && ContainsLabel(stat->labels(), label))
3472 return true;
3473 }
3474 return false;
3475}
3476
3477
3478BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3479 bool anonymous = label.is_null();
3480 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3481 BreakableStatement* stat = t->node()->AsBreakableStatement();
3482 if (stat == NULL) continue;
3483 if ((anonymous && stat->is_target_for_anonymous()) ||
3484 (!anonymous && ContainsLabel(stat->labels(), label))) {
3485 RegisterTargetUse(stat->break_target(), t->previous());
3486 return stat;
3487 }
3488 }
3489 return NULL;
3490}
3491
3492
3493IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3494 bool* ok) {
3495 bool anonymous = label.is_null();
3496 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3497 IterationStatement* stat = t->node()->AsIterationStatement();
3498 if (stat == NULL) continue;
3499
3500 ASSERT(stat->is_target_for_anonymous());
3501 if (anonymous || ContainsLabel(stat->labels(), label)) {
3502 RegisterTargetUse(stat->continue_target(), t->previous());
3503 return stat;
3504 }
3505 }
3506 return NULL;
3507}
3508
3509
3510void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) {
3511 // Register that a break target found at the given stop in the
3512 // target stack has been used from the top of the target stack. Add
3513 // the break target to any TargetCollectors passed on the stack.
3514 for (Target* t = target_stack_; t != stop; t = t->previous()) {
3515 TargetCollector* collector = t->node()->AsTargetCollector();
3516 if (collector != NULL) collector->AddTarget(target);
3517 }
3518}
3519
3520
3521Literal* Parser::NewNumberLiteral(double number) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003522 return new Literal(Factory::NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00003523}
3524
3525
3526Expression* Parser::NewThrowReferenceError(Handle<String> type) {
3527 return NewThrowError(Factory::MakeReferenceError_symbol(),
3528 type, HandleVector<Object>(NULL, 0));
3529}
3530
3531
3532Expression* Parser::NewThrowSyntaxError(Handle<String> type,
3533 Handle<Object> first) {
3534 int argc = first.is_null() ? 0 : 1;
3535 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
3536 return NewThrowError(Factory::MakeSyntaxError_symbol(), type, arguments);
3537}
3538
3539
3540Expression* Parser::NewThrowTypeError(Handle<String> type,
3541 Handle<Object> first,
3542 Handle<Object> second) {
3543 ASSERT(!first.is_null() && !second.is_null());
3544 Handle<Object> elements[] = { first, second };
3545 Vector< Handle<Object> > arguments =
3546 HandleVector<Object>(elements, ARRAY_SIZE(elements));
3547 return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments);
3548}
3549
3550
3551Expression* Parser::NewThrowError(Handle<String> constructor,
3552 Handle<String> type,
3553 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003554 int argc = arguments.length();
3555 Handle<JSArray> array = Factory::NewJSArray(argc, TENURED);
3556 ASSERT(array->IsJSArray() && array->HasFastElements());
3557 for (int i = 0; i < argc; i++) {
3558 Handle<Object> element = arguments[i];
3559 if (!element.is_null()) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003560 // We know this doesn't cause a GC here because we allocated the JSArray
3561 // large enough.
John Reck59135872010-11-02 12:39:01 -07003562 array->SetFastElement(i, *element)->ToObjectUnchecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003563 }
3564 }
3565 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
3566 args->Add(new Literal(type));
3567 args->Add(new Literal(array));
3568 return new Throw(new CallRuntime(constructor, NULL, args),
3569 scanner().location().beg_pos);
3570}
3571
Leon Clarke4515c472010-02-03 11:58:03 +00003572// ----------------------------------------------------------------------------
3573// JSON
3574
Ben Murdochb0fe1622011-05-05 13:52:32 +01003575Handle<Object> JsonParser::ParseJson(Handle<String> script,
3576 UC16CharacterStream* source) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08003577 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003578 stack_overflow_ = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003579 Handle<Object> result = ParseJsonValue();
3580 if (result.is_null() || scanner_.Next() != Token::EOS) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003581 if (stack_overflow_) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003582 // Scanner failed.
3583 Top::StackOverflow();
3584 } else {
3585 // Parse failed. Scanner's current token is the unexpected token.
3586 Token::Value token = scanner_.current_token();
3587
3588 const char* message;
3589 const char* name_opt = NULL;
3590
3591 switch (token) {
3592 case Token::EOS:
3593 message = "unexpected_eos";
3594 break;
3595 case Token::NUMBER:
3596 message = "unexpected_token_number";
3597 break;
3598 case Token::STRING:
3599 message = "unexpected_token_string";
3600 break;
3601 case Token::IDENTIFIER:
3602 message = "unexpected_token_identifier";
3603 break;
3604 default:
3605 message = "unexpected_token";
3606 name_opt = Token::String(token);
3607 ASSERT(name_opt != NULL);
3608 break;
3609 }
3610
3611 Scanner::Location source_location = scanner_.location();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003612 MessageLocation location(Factory::NewScript(script),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003613 source_location.beg_pos,
3614 source_location.end_pos);
3615 int argc = (name_opt == NULL) ? 0 : 1;
3616 Handle<JSArray> array = Factory::NewJSArray(argc);
3617 if (name_opt != NULL) {
3618 SetElement(array,
3619 0,
3620 Factory::NewStringFromUtf8(CStrVector(name_opt)));
3621 }
3622 Handle<Object> result = Factory::NewSyntaxError(message, array);
3623 Top::Throw(*result, &location);
3624 return Handle<Object>::null();
3625 }
3626 }
Leon Clarke4515c472010-02-03 11:58:03 +00003627 return result;
3628}
3629
3630
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003631Handle<String> JsonParser::GetString() {
3632 int literal_length = scanner_.literal_length();
3633 if (literal_length == 0) {
3634 return Factory::empty_string();
3635 }
Steve Block9fac8402011-05-12 15:51:54 +01003636 if (scanner_.is_literal_ascii()) {
3637 return Factory::NewStringFromAscii(scanner_.literal_ascii_string());
3638 } else {
3639 return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string());
3640 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003641}
3642
3643
Leon Clarke4515c472010-02-03 11:58:03 +00003644// Parse any JSON value.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003645Handle<Object> JsonParser::ParseJsonValue() {
3646 Token::Value token = scanner_.Next();
Leon Clarke4515c472010-02-03 11:58:03 +00003647 switch (token) {
3648 case Token::STRING: {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003649 return GetString();
Leon Clarke4515c472010-02-03 11:58:03 +00003650 }
3651 case Token::NUMBER: {
Steve Block9fac8402011-05-12 15:51:54 +01003652 ASSERT(scanner_.is_literal_ascii());
3653 double value = StringToDouble(scanner_.literal_ascii_string(),
Leon Clarke4515c472010-02-03 11:58:03 +00003654 NO_FLAGS, // Hex, octal or trailing junk.
3655 OS::nan_value());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003656 return Factory::NewNumber(value);
Leon Clarke4515c472010-02-03 11:58:03 +00003657 }
3658 case Token::FALSE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003659 return Factory::false_value();
Leon Clarke4515c472010-02-03 11:58:03 +00003660 case Token::TRUE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003661 return Factory::true_value();
Leon Clarke4515c472010-02-03 11:58:03 +00003662 case Token::NULL_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003663 return Factory::null_value();
3664 case Token::LBRACE:
3665 return ParseJsonObject();
3666 case Token::LBRACK:
3667 return ParseJsonArray();
Leon Clarke4515c472010-02-03 11:58:03 +00003668 default:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003669 return ReportUnexpectedToken();
Leon Clarke4515c472010-02-03 11:58:03 +00003670 }
3671}
3672
3673
3674// Parse a JSON object. Scanner must be right after '{' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003675Handle<Object> JsonParser::ParseJsonObject() {
3676 Handle<JSFunction> object_constructor(
3677 Top::global_context()->object_function());
3678 Handle<JSObject> json_object = Factory::NewJSObject(object_constructor);
3679 if (scanner_.peek() == Token::RBRACE) {
3680 scanner_.Next();
3681 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003682 if (StackLimitCheck().HasOverflowed()) {
3683 stack_overflow_ = true;
3684 return Handle<Object>::null();
3685 }
Leon Clarke4515c472010-02-03 11:58:03 +00003686 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003687 if (scanner_.Next() != Token::STRING) {
3688 return ReportUnexpectedToken();
3689 }
3690 Handle<String> key = GetString();
3691 if (scanner_.Next() != Token::COLON) {
3692 return ReportUnexpectedToken();
3693 }
3694 Handle<Object> value = ParseJsonValue();
3695 if (value.is_null()) return Handle<Object>::null();
Leon Clarke4515c472010-02-03 11:58:03 +00003696 uint32_t index;
3697 if (key->AsArrayIndex(&index)) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01003698 SetOwnElement(json_object, index, value);
Leon Clarke4515c472010-02-03 11:58:03 +00003699 } else {
Ben Murdoch086aeea2011-05-13 15:57:08 +01003700 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
Leon Clarke4515c472010-02-03 11:58:03 +00003701 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003702 } while (scanner_.Next() == Token::COMMA);
3703 if (scanner_.current_token() != Token::RBRACE) {
3704 return ReportUnexpectedToken();
3705 }
Leon Clarke4515c472010-02-03 11:58:03 +00003706 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003707 return json_object;
Leon Clarke4515c472010-02-03 11:58:03 +00003708}
3709
3710
3711// Parse a JSON array. Scanner must be right after '[' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003712Handle<Object> JsonParser::ParseJsonArray() {
3713 ZoneScope zone_scope(DELETE_ON_EXIT);
3714 ZoneList<Handle<Object> > elements(4);
Leon Clarke4515c472010-02-03 11:58:03 +00003715
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003716 Token::Value token = scanner_.peek();
3717 if (token == Token::RBRACK) {
3718 scanner_.Next();
3719 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003720 if (StackLimitCheck().HasOverflowed()) {
3721 stack_overflow_ = true;
3722 return Handle<Object>::null();
3723 }
Leon Clarke4515c472010-02-03 11:58:03 +00003724 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003725 Handle<Object> element = ParseJsonValue();
3726 if (element.is_null()) return Handle<Object>::null();
3727 elements.Add(element);
3728 token = scanner_.Next();
3729 } while (token == Token::COMMA);
3730 if (token != Token::RBRACK) {
3731 return ReportUnexpectedToken();
3732 }
Leon Clarke4515c472010-02-03 11:58:03 +00003733 }
Leon Clarke4515c472010-02-03 11:58:03 +00003734
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003735 // Allocate a fixed array with all the elements.
3736 Handle<FixedArray> fast_elements =
3737 Factory::NewFixedArray(elements.length());
Leon Clarke4515c472010-02-03 11:58:03 +00003738
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003739 for (int i = 0, n = elements.length(); i < n; i++) {
3740 fast_elements->set(i, *elements[i]);
3741 }
Leon Clarke4515c472010-02-03 11:58:03 +00003742
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003743 return Factory::NewJSArrayWithElements(fast_elements);
Leon Clarke4515c472010-02-03 11:58:03 +00003744}
3745
Steve Blocka7e24c12009-10-30 11:49:00 +00003746// ----------------------------------------------------------------------------
3747// Regular expressions
3748
3749
3750RegExpParser::RegExpParser(FlatStringReader* in,
3751 Handle<String>* error,
3752 bool multiline)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003753 : error_(error),
3754 captures_(NULL),
3755 in_(in),
3756 current_(kEndMarker),
3757 next_pos_(0),
3758 capture_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +00003759 has_more_(true),
3760 multiline_(multiline),
Steve Blocka7e24c12009-10-30 11:49:00 +00003761 simple_(false),
3762 contains_anchor_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00003763 is_scanned_for_captures_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00003764 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003765 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00003766}
3767
3768
3769uc32 RegExpParser::Next() {
3770 if (has_next()) {
3771 return in()->Get(next_pos_);
3772 } else {
3773 return kEndMarker;
3774 }
3775}
3776
3777
3778void RegExpParser::Advance() {
3779 if (next_pos_ < in()->length()) {
3780 StackLimitCheck check;
3781 if (check.HasOverflowed()) {
3782 ReportError(CStrVector(Top::kStackOverflowMessage));
3783 } else if (Zone::excess_allocation()) {
3784 ReportError(CStrVector("Regular expression too large"));
3785 } else {
3786 current_ = in()->Get(next_pos_);
3787 next_pos_++;
3788 }
3789 } else {
3790 current_ = kEndMarker;
3791 has_more_ = false;
3792 }
3793}
3794
3795
3796void RegExpParser::Reset(int pos) {
3797 next_pos_ = pos;
3798 Advance();
3799}
3800
3801
3802void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003803 next_pos_ += dist - 1;
3804 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00003805}
3806
3807
3808bool RegExpParser::simple() {
3809 return simple_;
3810}
3811
3812RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
3813 failed_ = true;
3814 *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
3815 // Zip to the end to make sure the no more input is read.
3816 current_ = kEndMarker;
3817 next_pos_ = in()->length();
3818 return NULL;
3819}
3820
3821
3822// Pattern ::
3823// Disjunction
3824RegExpTree* RegExpParser::ParsePattern() {
3825 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
3826 ASSERT(!has_more());
3827 // If the result of parsing is a literal string atom, and it has the
3828 // same length as the input, then the atom is identical to the input.
3829 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
3830 simple_ = true;
3831 }
3832 return result;
3833}
3834
3835
3836// Disjunction ::
3837// Alternative
3838// Alternative | Disjunction
3839// Alternative ::
3840// [empty]
3841// Term Alternative
3842// Term ::
3843// Assertion
3844// Atom
3845// Atom Quantifier
3846RegExpTree* RegExpParser::ParseDisjunction() {
3847 // Used to store current state while parsing subexpressions.
3848 RegExpParserState initial_state(NULL, INITIAL, 0);
3849 RegExpParserState* stored_state = &initial_state;
3850 // Cache the builder in a local variable for quick access.
3851 RegExpBuilder* builder = initial_state.builder();
3852 while (true) {
3853 switch (current()) {
3854 case kEndMarker:
3855 if (stored_state->IsSubexpression()) {
3856 // Inside a parenthesized group when hitting end of input.
3857 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
3858 }
3859 ASSERT_EQ(INITIAL, stored_state->group_type());
3860 // Parsing completed successfully.
3861 return builder->ToRegExp();
3862 case ')': {
3863 if (!stored_state->IsSubexpression()) {
3864 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
3865 }
3866 ASSERT_NE(INITIAL, stored_state->group_type());
3867
3868 Advance();
3869 // End disjunction parsing and convert builder content to new single
3870 // regexp atom.
3871 RegExpTree* body = builder->ToRegExp();
3872
3873 int end_capture_index = captures_started();
3874
3875 int capture_index = stored_state->capture_index();
3876 SubexpressionType type = stored_state->group_type();
3877
3878 // Restore previous state.
3879 stored_state = stored_state->previous_state();
3880 builder = stored_state->builder();
3881
3882 // Build result of subexpression.
3883 if (type == CAPTURE) {
3884 RegExpCapture* capture = new RegExpCapture(body, capture_index);
3885 captures_->at(capture_index - 1) = capture;
3886 body = capture;
3887 } else if (type != GROUPING) {
3888 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
3889 bool is_positive = (type == POSITIVE_LOOKAHEAD);
3890 body = new RegExpLookahead(body,
3891 is_positive,
3892 end_capture_index - capture_index,
3893 capture_index);
3894 }
3895 builder->AddAtom(body);
3896 break;
3897 }
3898 case '|': {
3899 Advance();
3900 builder->NewAlternative();
3901 continue;
3902 }
3903 case '*':
3904 case '+':
3905 case '?':
3906 return ReportError(CStrVector("Nothing to repeat"));
3907 case '^': {
3908 Advance();
3909 if (multiline_) {
3910 builder->AddAssertion(
3911 new RegExpAssertion(RegExpAssertion::START_OF_LINE));
3912 } else {
3913 builder->AddAssertion(
3914 new RegExpAssertion(RegExpAssertion::START_OF_INPUT));
3915 set_contains_anchor();
3916 }
3917 continue;
3918 }
3919 case '$': {
3920 Advance();
3921 RegExpAssertion::Type type =
3922 multiline_ ? RegExpAssertion::END_OF_LINE :
3923 RegExpAssertion::END_OF_INPUT;
3924 builder->AddAssertion(new RegExpAssertion(type));
3925 continue;
3926 }
3927 case '.': {
3928 Advance();
3929 // everything except \x0a, \x0d, \u2028 and \u2029
3930 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
3931 CharacterRange::AddClassEscape('.', ranges);
3932 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
3933 builder->AddAtom(atom);
3934 break;
3935 }
3936 case '(': {
3937 SubexpressionType type = CAPTURE;
3938 Advance();
3939 if (current() == '?') {
3940 switch (Next()) {
3941 case ':':
3942 type = GROUPING;
3943 break;
3944 case '=':
3945 type = POSITIVE_LOOKAHEAD;
3946 break;
3947 case '!':
3948 type = NEGATIVE_LOOKAHEAD;
3949 break;
3950 default:
3951 ReportError(CStrVector("Invalid group") CHECK_FAILED);
3952 break;
3953 }
3954 Advance(2);
3955 } else {
3956 if (captures_ == NULL) {
3957 captures_ = new ZoneList<RegExpCapture*>(2);
3958 }
3959 if (captures_started() >= kMaxCaptures) {
3960 ReportError(CStrVector("Too many captures") CHECK_FAILED);
3961 }
3962 captures_->Add(NULL);
3963 }
3964 // Store current state and begin new disjunction parsing.
3965 stored_state = new RegExpParserState(stored_state,
3966 type,
3967 captures_started());
3968 builder = stored_state->builder();
3969 break;
3970 }
3971 case '[': {
3972 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
3973 builder->AddAtom(atom);
3974 break;
3975 }
3976 // Atom ::
3977 // \ AtomEscape
3978 case '\\':
3979 switch (Next()) {
3980 case kEndMarker:
3981 return ReportError(CStrVector("\\ at end of pattern"));
3982 case 'b':
3983 Advance(2);
3984 builder->AddAssertion(
3985 new RegExpAssertion(RegExpAssertion::BOUNDARY));
3986 continue;
3987 case 'B':
3988 Advance(2);
3989 builder->AddAssertion(
3990 new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
3991 continue;
3992 // AtomEscape ::
3993 // CharacterClassEscape
3994 //
3995 // CharacterClassEscape :: one of
3996 // d D s S w W
3997 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
3998 uc32 c = Next();
3999 Advance(2);
4000 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4001 CharacterRange::AddClassEscape(c, ranges);
4002 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
4003 builder->AddAtom(atom);
4004 break;
4005 }
4006 case '1': case '2': case '3': case '4': case '5': case '6':
4007 case '7': case '8': case '9': {
4008 int index = 0;
4009 if (ParseBackReferenceIndex(&index)) {
4010 RegExpCapture* capture = NULL;
4011 if (captures_ != NULL && index <= captures_->length()) {
4012 capture = captures_->at(index - 1);
4013 }
4014 if (capture == NULL) {
4015 builder->AddEmpty();
4016 break;
4017 }
4018 RegExpTree* atom = new RegExpBackReference(capture);
4019 builder->AddAtom(atom);
4020 break;
4021 }
4022 uc32 first_digit = Next();
4023 if (first_digit == '8' || first_digit == '9') {
4024 // Treat as identity escape
4025 builder->AddCharacter(first_digit);
4026 Advance(2);
4027 break;
4028 }
4029 }
4030 // FALLTHROUGH
4031 case '0': {
4032 Advance();
4033 uc32 octal = ParseOctalLiteral();
4034 builder->AddCharacter(octal);
4035 break;
4036 }
4037 // ControlEscape :: one of
4038 // f n r t v
4039 case 'f':
4040 Advance(2);
4041 builder->AddCharacter('\f');
4042 break;
4043 case 'n':
4044 Advance(2);
4045 builder->AddCharacter('\n');
4046 break;
4047 case 'r':
4048 Advance(2);
4049 builder->AddCharacter('\r');
4050 break;
4051 case 't':
4052 Advance(2);
4053 builder->AddCharacter('\t');
4054 break;
4055 case 'v':
4056 Advance(2);
4057 builder->AddCharacter('\v');
4058 break;
4059 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004060 Advance();
4061 uc32 controlLetter = Next();
4062 // Special case if it is an ASCII letter.
4063 // Convert lower case letters to uppercase.
4064 uc32 letter = controlLetter & ~('a' ^ 'A');
4065 if (letter < 'A' || 'Z' < letter) {
4066 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4067 // This is outside the specification. We match JSC in
4068 // reading the backslash as a literal character instead
4069 // of as starting an escape.
4070 builder->AddCharacter('\\');
4071 } else {
4072 Advance(2);
4073 builder->AddCharacter(controlLetter & 0x1f);
4074 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004075 break;
4076 }
4077 case 'x': {
4078 Advance(2);
4079 uc32 value;
4080 if (ParseHexEscape(2, &value)) {
4081 builder->AddCharacter(value);
4082 } else {
4083 builder->AddCharacter('x');
4084 }
4085 break;
4086 }
4087 case 'u': {
4088 Advance(2);
4089 uc32 value;
4090 if (ParseHexEscape(4, &value)) {
4091 builder->AddCharacter(value);
4092 } else {
4093 builder->AddCharacter('u');
4094 }
4095 break;
4096 }
4097 default:
4098 // Identity escape.
4099 builder->AddCharacter(Next());
4100 Advance(2);
4101 break;
4102 }
4103 break;
4104 case '{': {
4105 int dummy;
4106 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4107 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4108 }
4109 // fallthrough
4110 }
4111 default:
4112 builder->AddCharacter(current());
4113 Advance();
4114 break;
4115 } // end switch(current())
4116
4117 int min;
4118 int max;
4119 switch (current()) {
4120 // QuantifierPrefix ::
4121 // *
4122 // +
4123 // ?
4124 // {
4125 case '*':
4126 min = 0;
4127 max = RegExpTree::kInfinity;
4128 Advance();
4129 break;
4130 case '+':
4131 min = 1;
4132 max = RegExpTree::kInfinity;
4133 Advance();
4134 break;
4135 case '?':
4136 min = 0;
4137 max = 1;
4138 Advance();
4139 break;
4140 case '{':
4141 if (ParseIntervalQuantifier(&min, &max)) {
4142 if (max < min) {
4143 ReportError(CStrVector("numbers out of order in {} quantifier.")
4144 CHECK_FAILED);
4145 }
4146 break;
4147 } else {
4148 continue;
4149 }
4150 default:
4151 continue;
4152 }
Leon Clarkee46be812010-01-19 14:06:41 +00004153 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004154 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004155 type = RegExpQuantifier::NON_GREEDY;
4156 Advance();
4157 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4158 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4159 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004160 Advance();
4161 }
Leon Clarkee46be812010-01-19 14:06:41 +00004162 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004163 }
4164}
4165
4166class SourceCharacter {
4167 public:
4168 static bool Is(uc32 c) {
4169 switch (c) {
4170 // case ']': case '}':
4171 // In spidermonkey and jsc these are treated as source characters
4172 // so we do too.
4173 case '^': case '$': case '\\': case '.': case '*': case '+':
4174 case '?': case '(': case ')': case '[': case '{': case '|':
4175 case RegExpParser::kEndMarker:
4176 return false;
4177 default:
4178 return true;
4179 }
4180 }
4181};
4182
4183
4184static unibrow::Predicate<SourceCharacter> source_character;
4185
4186
4187static inline bool IsSourceCharacter(uc32 c) {
4188 return source_character.get(c);
4189}
4190
4191#ifdef DEBUG
4192// Currently only used in an ASSERT.
4193static bool IsSpecialClassEscape(uc32 c) {
4194 switch (c) {
4195 case 'd': case 'D':
4196 case 's': case 'S':
4197 case 'w': case 'W':
4198 return true;
4199 default:
4200 return false;
4201 }
4202}
4203#endif
4204
4205
4206// In order to know whether an escape is a backreference or not we have to scan
4207// the entire regexp and find the number of capturing parentheses. However we
4208// don't want to scan the regexp twice unless it is necessary. This mini-parser
4209// is called when needed. It can see the difference between capturing and
4210// noncapturing parentheses and can skip character classes and backslash-escaped
4211// characters.
4212void RegExpParser::ScanForCaptures() {
4213 // Start with captures started previous to current position
4214 int capture_count = captures_started();
4215 // Add count of captures after this position.
4216 int n;
4217 while ((n = current()) != kEndMarker) {
4218 Advance();
4219 switch (n) {
4220 case '\\':
4221 Advance();
4222 break;
4223 case '[': {
4224 int c;
4225 while ((c = current()) != kEndMarker) {
4226 Advance();
4227 if (c == '\\') {
4228 Advance();
4229 } else {
4230 if (c == ']') break;
4231 }
4232 }
4233 break;
4234 }
4235 case '(':
4236 if (current() != '?') capture_count++;
4237 break;
4238 }
4239 }
4240 capture_count_ = capture_count;
4241 is_scanned_for_captures_ = true;
4242}
4243
4244
4245bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4246 ASSERT_EQ('\\', current());
4247 ASSERT('1' <= Next() && Next() <= '9');
4248 // Try to parse a decimal literal that is no greater than the total number
4249 // of left capturing parentheses in the input.
4250 int start = position();
4251 int value = Next() - '0';
4252 Advance(2);
4253 while (true) {
4254 uc32 c = current();
4255 if (IsDecimalDigit(c)) {
4256 value = 10 * value + (c - '0');
4257 if (value > kMaxCaptures) {
4258 Reset(start);
4259 return false;
4260 }
4261 Advance();
4262 } else {
4263 break;
4264 }
4265 }
4266 if (value > captures_started()) {
4267 if (!is_scanned_for_captures_) {
4268 int saved_position = position();
4269 ScanForCaptures();
4270 Reset(saved_position);
4271 }
4272 if (value > capture_count_) {
4273 Reset(start);
4274 return false;
4275 }
4276 }
4277 *index_out = value;
4278 return true;
4279}
4280
4281
4282// QuantifierPrefix ::
4283// { DecimalDigits }
4284// { DecimalDigits , }
4285// { DecimalDigits , DecimalDigits }
4286//
4287// Returns true if parsing succeeds, and set the min_out and max_out
4288// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4289bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4290 ASSERT_EQ(current(), '{');
4291 int start = position();
4292 Advance();
4293 int min = 0;
4294 if (!IsDecimalDigit(current())) {
4295 Reset(start);
4296 return false;
4297 }
4298 while (IsDecimalDigit(current())) {
4299 int next = current() - '0';
4300 if (min > (RegExpTree::kInfinity - next) / 10) {
4301 // Overflow. Skip past remaining decimal digits and return -1.
4302 do {
4303 Advance();
4304 } while (IsDecimalDigit(current()));
4305 min = RegExpTree::kInfinity;
4306 break;
4307 }
4308 min = 10 * min + next;
4309 Advance();
4310 }
4311 int max = 0;
4312 if (current() == '}') {
4313 max = min;
4314 Advance();
4315 } else if (current() == ',') {
4316 Advance();
4317 if (current() == '}') {
4318 max = RegExpTree::kInfinity;
4319 Advance();
4320 } else {
4321 while (IsDecimalDigit(current())) {
4322 int next = current() - '0';
4323 if (max > (RegExpTree::kInfinity - next) / 10) {
4324 do {
4325 Advance();
4326 } while (IsDecimalDigit(current()));
4327 max = RegExpTree::kInfinity;
4328 break;
4329 }
4330 max = 10 * max + next;
4331 Advance();
4332 }
4333 if (current() != '}') {
4334 Reset(start);
4335 return false;
4336 }
4337 Advance();
4338 }
4339 } else {
4340 Reset(start);
4341 return false;
4342 }
4343 *min_out = min;
4344 *max_out = max;
4345 return true;
4346}
4347
4348
Steve Blocka7e24c12009-10-30 11:49:00 +00004349uc32 RegExpParser::ParseOctalLiteral() {
4350 ASSERT('0' <= current() && current() <= '7');
4351 // For compatibility with some other browsers (not all), we parse
4352 // up to three octal digits with a value below 256.
4353 uc32 value = current() - '0';
4354 Advance();
4355 if ('0' <= current() && current() <= '7') {
4356 value = value * 8 + current() - '0';
4357 Advance();
4358 if (value < 32 && '0' <= current() && current() <= '7') {
4359 value = value * 8 + current() - '0';
4360 Advance();
4361 }
4362 }
4363 return value;
4364}
4365
4366
4367bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4368 int start = position();
4369 uc32 val = 0;
4370 bool done = false;
4371 for (int i = 0; !done; i++) {
4372 uc32 c = current();
4373 int d = HexValue(c);
4374 if (d < 0) {
4375 Reset(start);
4376 return false;
4377 }
4378 val = val * 16 + d;
4379 Advance();
4380 if (i == length - 1) {
4381 done = true;
4382 }
4383 }
4384 *value = val;
4385 return true;
4386}
4387
4388
4389uc32 RegExpParser::ParseClassCharacterEscape() {
4390 ASSERT(current() == '\\');
4391 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4392 Advance();
4393 switch (current()) {
4394 case 'b':
4395 Advance();
4396 return '\b';
4397 // ControlEscape :: one of
4398 // f n r t v
4399 case 'f':
4400 Advance();
4401 return '\f';
4402 case 'n':
4403 Advance();
4404 return '\n';
4405 case 'r':
4406 Advance();
4407 return '\r';
4408 case 't':
4409 Advance();
4410 return '\t';
4411 case 'v':
4412 Advance();
4413 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004414 case 'c': {
4415 uc32 controlLetter = Next();
4416 uc32 letter = controlLetter & ~('A' ^ 'a');
4417 // For compatibility with JSC, inside a character class
4418 // we also accept digits and underscore as control characters.
4419 if ((controlLetter >= '0' && controlLetter <= '9') ||
4420 controlLetter == '_' ||
4421 (letter >= 'A' && letter <= 'Z')) {
4422 Advance(2);
4423 // Control letters mapped to ASCII control characters in the range
4424 // 0x00-0x1f.
4425 return controlLetter & 0x1f;
4426 }
4427 // We match JSC in reading the backslash as a literal
4428 // character instead of as starting an escape.
4429 return '\\';
4430 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004431 case '0': case '1': case '2': case '3': case '4': case '5':
4432 case '6': case '7':
4433 // For compatibility, we interpret a decimal escape that isn't
4434 // a back reference (and therefore either \0 or not valid according
4435 // to the specification) as a 1..3 digit octal character code.
4436 return ParseOctalLiteral();
4437 case 'x': {
4438 Advance();
4439 uc32 value;
4440 if (ParseHexEscape(2, &value)) {
4441 return value;
4442 }
4443 // If \x is not followed by a two-digit hexadecimal, treat it
4444 // as an identity escape.
4445 return 'x';
4446 }
4447 case 'u': {
4448 Advance();
4449 uc32 value;
4450 if (ParseHexEscape(4, &value)) {
4451 return value;
4452 }
4453 // If \u is not followed by a four-digit hexadecimal, treat it
4454 // as an identity escape.
4455 return 'u';
4456 }
4457 default: {
4458 // Extended identity escape. We accept any character that hasn't
4459 // been matched by a more specific case, not just the subset required
4460 // by the ECMAScript specification.
4461 uc32 result = current();
4462 Advance();
4463 return result;
4464 }
4465 }
4466 return 0;
4467}
4468
4469
4470CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4471 ASSERT_EQ(0, *char_class);
4472 uc32 first = current();
4473 if (first == '\\') {
4474 switch (Next()) {
4475 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4476 *char_class = Next();
4477 Advance(2);
4478 return CharacterRange::Singleton(0); // Return dummy value.
4479 }
4480 case kEndMarker:
4481 return ReportError(CStrVector("\\ at end of pattern"));
4482 default:
4483 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4484 return CharacterRange::Singleton(c);
4485 }
4486 } else {
4487 Advance();
4488 return CharacterRange::Singleton(first);
4489 }
4490}
4491
4492
Ben Murdochb0fe1622011-05-05 13:52:32 +01004493static const uc16 kNoCharClass = 0;
4494
4495// Adds range or pre-defined character class to character ranges.
4496// If char_class is not kInvalidClass, it's interpreted as a class
4497// escape (i.e., 's' means whitespace, from '\s').
4498static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4499 uc16 char_class,
4500 CharacterRange range) {
4501 if (char_class != kNoCharClass) {
4502 CharacterRange::AddClassEscape(char_class, ranges);
4503 } else {
4504 ranges->Add(range);
4505 }
4506}
4507
4508
Steve Blocka7e24c12009-10-30 11:49:00 +00004509RegExpTree* RegExpParser::ParseCharacterClass() {
4510 static const char* kUnterminated = "Unterminated character class";
4511 static const char* kRangeOutOfOrder = "Range out of order in character class";
4512
4513 ASSERT_EQ(current(), '[');
4514 Advance();
4515 bool is_negated = false;
4516 if (current() == '^') {
4517 is_negated = true;
4518 Advance();
4519 }
4520 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4521 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004522 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004523 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004524 if (current() == '-') {
4525 Advance();
4526 if (current() == kEndMarker) {
4527 // If we reach the end we break out of the loop and let the
4528 // following code report an error.
4529 break;
4530 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004531 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004532 ranges->Add(CharacterRange::Singleton('-'));
4533 break;
4534 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004535 uc16 char_class_2 = kNoCharClass;
4536 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4537 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4538 // Either end is an escaped character class. Treat the '-' verbatim.
4539 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004540 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004541 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004542 continue;
4543 }
4544 if (first.from() > next.to()) {
4545 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4546 }
4547 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4548 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004549 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004550 }
4551 }
4552 if (!has_more()) {
4553 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4554 }
4555 Advance();
4556 if (ranges->length() == 0) {
4557 ranges->Add(CharacterRange::Everything());
4558 is_negated = !is_negated;
4559 }
4560 return new RegExpCharacterClass(ranges, is_negated);
4561}
4562
4563
4564// ----------------------------------------------------------------------------
4565// The Parser interface.
4566
Steve Blocka7e24c12009-10-30 11:49:00 +00004567ParserMessage::~ParserMessage() {
4568 for (int i = 0; i < args().length(); i++)
4569 DeleteArray(args()[i]);
4570 DeleteArray(args().start());
4571}
4572
4573
4574ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01004575 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00004576}
4577
4578
4579int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01004580 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00004581}
4582
4583
Leon Clarkef7060e22010-06-03 12:02:55 +01004584const char* ScriptDataImpl::Data() {
4585 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00004586}
4587
4588
Leon Clarkee46be812010-01-19 14:06:41 +00004589bool ScriptDataImpl::HasError() {
4590 return has_error();
4591}
4592
4593
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004594void ScriptDataImpl::Initialize() {
4595 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004596 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
4597 function_index_ = PreparseDataConstants::kHeaderSize;
4598 int symbol_data_offset = PreparseDataConstants::kHeaderSize
4599 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004600 if (store_.length() > symbol_data_offset) {
4601 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
4602 } else {
4603 // Partial preparse causes no symbol information.
4604 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4605 }
4606 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4607 }
4608}
4609
4610
4611int ScriptDataImpl::ReadNumber(byte** source) {
4612 // Reads a number from symbol_data_ in base 128. The most significant
4613 // bit marks that there are more digits.
4614 // If the first byte is 0x80 (kNumberTerminator), it would normally
4615 // represent a leading zero. Since that is useless, and therefore won't
4616 // appear as the first digit of any actual value, it is used to
4617 // mark the end of the input stream.
4618 byte* data = *source;
4619 if (data >= symbol_data_end_) return -1;
4620 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004621 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004622 // End of stream marker.
4623 return -1;
4624 }
4625 int result = input & 0x7f;
4626 data++;
4627 while ((input & 0x80u) != 0) {
4628 if (data >= symbol_data_end_) return -1;
4629 input = *data;
4630 result = (result << 7) | (input & 0x7f);
4631 data++;
4632 }
4633 *source = data;
4634 return result;
4635}
4636
4637
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004638// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004639static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004640 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01004641 ParserRecorder* recorder) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004642 V8JavaScriptScanner scanner;
Steve Block9fac8402011-05-12 15:51:54 +01004643 scanner.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004644 intptr_t stack_limit = StackGuard::real_climit();
4645 if (!preparser::PreParser::PreParseProgram(&scanner,
4646 recorder,
4647 allow_lazy,
4648 stack_limit)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004649 Top::StackOverflow();
4650 return NULL;
4651 }
4652
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004653 // Extract the accumulated data from the recorder as a single
4654 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004655 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00004656 return new ScriptDataImpl(store);
4657}
4658
4659
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004660// Preparse, but only collect data that is immediately useful,
4661// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004662ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004663 v8::Extension* extension) {
4664 bool allow_lazy = FLAG_lazy && (extension == NULL);
4665 if (!allow_lazy) {
4666 // Partial preparsing is only about lazily compiled functions.
4667 // If we don't allow lazy compilation, the log data will be empty.
4668 return NULL;
4669 }
4670 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01004671 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004672}
4673
4674
Ben Murdochb0fe1622011-05-05 13:52:32 +01004675ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004676 v8::Extension* extension) {
4677 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004678 bool allow_lazy = FLAG_lazy && (extension == NULL);
4679 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01004680 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004681}
4682
4683
4684bool RegExpParser::ParseRegExp(FlatStringReader* input,
4685 bool multiline,
4686 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004687 ASSERT(result != NULL);
4688 RegExpParser parser(input, &result->error, multiline);
4689 RegExpTree* tree = parser.ParsePattern();
4690 if (parser.failed()) {
4691 ASSERT(tree == NULL);
4692 ASSERT(!result->error.is_null());
4693 } else {
4694 ASSERT(tree != NULL);
4695 ASSERT(result->error.is_null());
4696 result->tree = tree;
4697 int capture_count = parser.captures_started();
4698 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
4699 result->contains_anchor = parser.contains_anchor();
4700 result->capture_count = capture_count;
4701 }
4702 return !parser.failed();
4703}
4704
4705
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004706bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01004707 ASSERT(info->function() == NULL);
4708 FunctionLiteral* result = NULL;
4709 Handle<Script> script = info->script();
4710 if (info->is_lazy()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004711 Parser parser(script, true, NULL, NULL);
Ben Murdochf87a2032010-10-22 12:50:53 +01004712 result = parser.ParseLazy(info->shared_info());
Leon Clarke4515c472010-02-03 11:58:03 +00004713 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01004714 bool allow_natives_syntax =
4715 FLAG_allow_natives_syntax || Bootstrapper::IsActive();
4716 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004717 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01004718 if (pre_data != NULL && pre_data->has_error()) {
4719 Scanner::Location loc = pre_data->MessageLocation();
4720 const char* message = pre_data->BuildMessage();
4721 Vector<const char*> args = pre_data->BuildArgs();
4722 parser.ReportMessageAt(loc, message, args);
4723 DeleteArray(message);
4724 for (int i = 0; i < args.length(); i++) {
4725 DeleteArray(args[i]);
4726 }
4727 DeleteArray(args.start());
4728 ASSERT(Top::has_pending_exception());
4729 } else {
4730 Handle<String> source = Handle<String>(String::cast(script->source()));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004731 result = parser.ParseProgram(source, info->is_global());
Ben Murdochf87a2032010-10-22 12:50:53 +01004732 }
Leon Clarke4515c472010-02-03 11:58:03 +00004733 }
Ben Murdochf87a2032010-10-22 12:50:53 +01004734
4735 info->SetFunction(result);
4736 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00004737}
4738
Steve Blocka7e24c12009-10-30 11:49:00 +00004739} } // namespace v8::internal