blob: 7ad64407a4d55a95691aaf93679091110d8d5e66 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 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"
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "ast-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#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
44namespace v8 {
45namespace internal {
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047// PositionStack is used for on-stack allocation of token positions for
48// new expressions. Please look at ParseNewExpression.
49
50class PositionStack {
51 public:
52 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
53 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
54
55 class Element {
56 public:
57 Element(PositionStack* stack, int value) {
58 previous_ = stack->top();
59 value_ = value;
60 stack->set_top(this);
61 }
62
63 private:
64 Element* previous() { return previous_; }
65 int value() { return value_; }
66 friend class PositionStack;
67 Element* previous_;
68 int value_;
69 };
70
71 bool is_empty() { return top_ == NULL; }
72 int pop() {
73 ASSERT(!is_empty());
74 int result = top_->value();
75 top_ = top_->previous();
76 return result;
77 }
78
79 private:
80 Element* top() { return top_; }
81 void set_top(Element* value) { top_ = value; }
82 Element* top_;
83 bool* ok_;
84};
85
86
Steve Blocka7e24c12009-10-30 11:49:00 +000087RegExpBuilder::RegExpBuilder()
Ben Murdoch8b112d22011-06-08 16:22:53 +010088 : zone_(Isolate::Current()->zone()),
89 pending_empty_(false),
90 characters_(NULL),
91 terms_(),
92 alternatives_()
Steve Blocka7e24c12009-10-30 11:49:00 +000093#ifdef DEBUG
Ben Murdoch8b112d22011-06-08 16:22:53 +010094 , last_added_(ADD_NONE)
Steve Blocka7e24c12009-10-30 11:49:00 +000095#endif
96 {}
97
98
99void RegExpBuilder::FlushCharacters() {
100 pending_empty_ = false;
101 if (characters_ != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100102 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 characters_ = NULL;
104 text_.Add(atom);
105 LAST(ADD_ATOM);
106 }
107}
108
109
110void RegExpBuilder::FlushText() {
111 FlushCharacters();
112 int num_text = text_.length();
113 if (num_text == 0) {
114 return;
115 } else if (num_text == 1) {
116 terms_.Add(text_.last());
117 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100118 RegExpText* text = new(zone()) RegExpText();
Steve Blocka7e24c12009-10-30 11:49:00 +0000119 for (int i = 0; i < num_text; i++)
120 text_.Get(i)->AppendToText(text);
121 terms_.Add(text);
122 }
123 text_.Clear();
124}
125
126
127void RegExpBuilder::AddCharacter(uc16 c) {
128 pending_empty_ = false;
129 if (characters_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000130 characters_ = new(zone()) ZoneList<uc16>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 }
132 characters_->Add(c);
133 LAST(ADD_CHAR);
134}
135
136
137void RegExpBuilder::AddEmpty() {
138 pending_empty_ = true;
139}
140
141
142void RegExpBuilder::AddAtom(RegExpTree* term) {
143 if (term->IsEmpty()) {
144 AddEmpty();
145 return;
146 }
147 if (term->IsTextElement()) {
148 FlushCharacters();
149 text_.Add(term);
150 } else {
151 FlushText();
152 terms_.Add(term);
153 }
154 LAST(ADD_ATOM);
155}
156
157
158void RegExpBuilder::AddAssertion(RegExpTree* assert) {
159 FlushText();
160 terms_.Add(assert);
161 LAST(ADD_ASSERT);
162}
163
164
165void RegExpBuilder::NewAlternative() {
166 FlushTerms();
167}
168
169
170void RegExpBuilder::FlushTerms() {
171 FlushText();
172 int num_terms = terms_.length();
173 RegExpTree* alternative;
174 if (num_terms == 0) {
175 alternative = RegExpEmpty::GetInstance();
176 } else if (num_terms == 1) {
177 alternative = terms_.last();
178 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100179 alternative = new(zone()) RegExpAlternative(terms_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 }
181 alternatives_.Add(alternative);
182 terms_.Clear();
183 LAST(ADD_NONE);
184}
185
186
187RegExpTree* RegExpBuilder::ToRegExp() {
188 FlushTerms();
189 int num_alternatives = alternatives_.length();
190 if (num_alternatives == 0) {
191 return RegExpEmpty::GetInstance();
192 }
193 if (num_alternatives == 1) {
194 return alternatives_.last();
195 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100196 return new(zone()) RegExpDisjunction(alternatives_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000197}
198
199
Leon Clarkee46be812010-01-19 14:06:41 +0000200void RegExpBuilder::AddQuantifierToAtom(int min,
201 int max,
202 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 if (pending_empty_) {
204 pending_empty_ = false;
205 return;
206 }
207 RegExpTree* atom;
208 if (characters_ != NULL) {
209 ASSERT(last_added_ == ADD_CHAR);
210 // Last atom was character.
211 Vector<const uc16> char_vector = characters_->ToConstVector();
212 int num_chars = char_vector.length();
213 if (num_chars > 1) {
214 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100215 text_.Add(new(zone()) RegExpAtom(prefix));
Steve Blocka7e24c12009-10-30 11:49:00 +0000216 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
217 }
218 characters_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100219 atom = new(zone()) RegExpAtom(char_vector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 FlushText();
221 } else if (text_.length() > 0) {
222 ASSERT(last_added_ == ADD_ATOM);
223 atom = text_.RemoveLast();
224 FlushText();
225 } else if (terms_.length() > 0) {
226 ASSERT(last_added_ == ADD_ATOM);
227 atom = terms_.RemoveLast();
228 if (atom->max_match() == 0) {
229 // Guaranteed to only match an empty string.
230 LAST(ADD_TERM);
231 if (min == 0) {
232 return;
233 }
234 terms_.Add(atom);
235 return;
236 }
237 } else {
238 // Only call immediately after adding an atom or character!
239 UNREACHABLE();
240 return;
241 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100242 terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 LAST(ADD_TERM);
244}
245
246
Steve Block9fac8402011-05-12 15:51:54 +0100247Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800248 // Length of symbol cache is the number of identified symbols.
249 // If we are larger than that, or negative, it's not a cached symbol.
250 // This might also happen if there is no preparser symbol data, even
251 // if there is some preparser data.
252 if (static_cast<unsigned>(symbol_id)
253 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100254 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100255 return isolate()->factory()->LookupAsciiSymbol(
256 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100257 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100258 return isolate()->factory()->LookupTwoByteSymbol(
259 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100260 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800261 }
Steve Block9fac8402011-05-12 15:51:54 +0100262 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800263}
264
265
Steve Block9fac8402011-05-12 15:51:54 +0100266Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800267 // Make sure the cache is large enough to hold the symbol identifier.
268 if (symbol_cache_.length() <= symbol_id) {
269 // Increase length to index + 1.
270 symbol_cache_.AddBlock(Handle<String>::null(),
271 symbol_id + 1 - symbol_cache_.length());
272 }
273 Handle<String> result = symbol_cache_.at(symbol_id);
274 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100275 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100276 result = isolate()->factory()->LookupAsciiSymbol(
277 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100278 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100279 result = isolate()->factory()->LookupTwoByteSymbol(
280 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100281 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800282 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100283 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 }
Steve Block44f0eee2011-05-26 01:26:41 +0100285 isolate()->counters()->total_preparse_symbols_skipped()->Increment();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800286 return result;
287}
Steve Blocka7e24c12009-10-30 11:49:00 +0000288
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800289
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100290FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
291 // The current pre-data entry must be a FunctionEntry with the given
292 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100293 if ((function_index_ + FunctionEntry::kSize <= store_.length())
294 && (static_cast<int>(store_[function_index_]) == start)) {
295 int index = function_index_;
296 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100297 return FunctionEntry(store_.SubVector(index,
298 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000299 }
300 return FunctionEntry();
301}
302
303
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100304int ScriptDataImpl::GetSymbolIdentifier() {
305 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100306}
307
308
Iain Merrick9ac36c92010-09-13 15:29:50 +0100309bool ScriptDataImpl::SanityCheck() {
310 // Check that the header data is valid and doesn't specify
311 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800312 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
313 if (magic() != PreparseDataConstants::kMagicNumber) return false;
314 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100315 if (has_error()) {
316 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800317 if (store_.length() <= PreparseDataConstants::kHeaderSize
318 + PreparseDataConstants::kMessageTextPos) {
319 return false;
320 }
321 if (Read(PreparseDataConstants::kMessageStartPos) >
322 Read(PreparseDataConstants::kMessageEndPos)) {
323 return false;
324 }
325 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
326 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100327 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800328 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
329 return false;
330 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100331 int length = static_cast<int>(Read(pos));
332 if (length < 0) return false;
333 pos += 1 + length;
334 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800335 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
336 return false;
337 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100338 return true;
339 }
340 // Check that the space allocated for function entries is sane.
341 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800342 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100343 if (functions_size < 0) return false;
344 if (functions_size % FunctionEntry::kSize != 0) return false;
345 // Check that the count of symbols is non-negative.
346 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800347 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100348 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100349 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100350 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800351 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100352 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 return true;
354}
355
356
Steve Block59151502010-09-22 15:07:15 +0100357
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100358const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000359 int length = start[0];
360 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100361 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000362 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100363 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000364 result[length] = '\0';
365 if (chars != NULL) *chars = length;
366 return result;
367}
368
Steve Blocka7e24c12009-10-30 11:49:00 +0000369Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800370 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
371 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000372 return Scanner::Location(beg_pos, end_pos);
373}
374
375
376const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800377 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100378 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000379}
380
381
382Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800383 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100385 // Position after text found by skipping past length field and
386 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800387 int pos = PreparseDataConstants::kMessageTextPos + 1
388 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 for (int i = 0; i < arg_count; i++) {
390 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100391 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 pos += count + 1;
393 }
394 return Vector<const char*>(array, arg_count);
395}
396
397
398unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800399 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000400}
401
402
403unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800404 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000405}
406
407
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800408Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100409 Scope* result = new(zone()) Scope(parent, type);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 result->Initialize(inside_with);
411 return result;
412}
413
Steve Blocka7e24c12009-10-30 11:49:00 +0000414// ----------------------------------------------------------------------------
415// Target is a support class to facilitate manipulation of the
416// Parser's target_stack_ (the stack of potential 'break' and
417// 'continue' statement targets). Upon construction, a new target is
418// added; it is removed upon destruction.
419
420class Target BASE_EMBEDDED {
421 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800422 Target(Target** variable, AstNode* node)
423 : variable_(variable), node_(node), previous_(*variable) {
424 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000425 }
426
427 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800428 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 }
430
431 Target* previous() { return previous_; }
432 AstNode* node() { return node_; }
433
434 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800435 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000436 AstNode* node_;
437 Target* previous_;
438};
439
440
441class TargetScope BASE_EMBEDDED {
442 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800443 explicit TargetScope(Target** variable)
444 : variable_(variable), previous_(*variable) {
445 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000446 }
447
448 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800449 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 }
451
452 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800453 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 Target* previous_;
455};
456
457
458// ----------------------------------------------------------------------------
459// LexicalScope is a support class to facilitate manipulation of the
460// Parser's scope stack. The constructor sets the parser's top scope
461// to the incoming scope, and the destructor resets it.
Steve Block44f0eee2011-05-26 01:26:41 +0100462//
Ben Murdoch8b112d22011-06-08 16:22:53 +0100463// Additionally, it stores transient information used during parsing.
Steve Block44f0eee2011-05-26 01:26:41 +0100464// These scopes are not kept around after parsing or referenced by syntax
465// trees so they can be stack-allocated and hence used by the pre-parser.
Steve Blocka7e24c12009-10-30 11:49:00 +0000466
467class LexicalScope BASE_EMBEDDED {
468 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100469 LexicalScope(Parser* parser, Scope* scope, Isolate* isolate);
470 ~LexicalScope();
471
472 int NextMaterializedLiteralIndex() {
473 int next_index =
474 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
475 materialized_literal_count_++;
476 return next_index;
477 }
478 int materialized_literal_count() { return materialized_literal_count_; }
479
480 void SetThisPropertyAssignmentInfo(
481 bool only_simple_this_property_assignments,
482 Handle<FixedArray> this_property_assignments) {
483 only_simple_this_property_assignments_ =
484 only_simple_this_property_assignments;
485 this_property_assignments_ = this_property_assignments;
486 }
487 bool only_simple_this_property_assignments() {
488 return only_simple_this_property_assignments_;
489 }
490 Handle<FixedArray> this_property_assignments() {
491 return this_property_assignments_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000492 }
493
Steve Block44f0eee2011-05-26 01:26:41 +0100494 void AddProperty() { expected_property_count_++; }
495 int expected_property_count() { return expected_property_count_; }
496
Steve Blocka7e24c12009-10-30 11:49:00 +0000497 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100498 // Captures the number of literals that need materialization in the
499 // function. Includes regexp literals, and boilerplate for object
500 // and array literals.
501 int materialized_literal_count_;
502
503 // Properties count estimation.
504 int expected_property_count_;
505
506 // Keeps track of assignments to properties of this. Used for
507 // optimizing constructors.
508 bool only_simple_this_property_assignments_;
509 Handle<FixedArray> this_property_assignments_;
510
Steve Block44f0eee2011-05-26 01:26:41 +0100511 // Bookkeeping
512 Parser* parser_;
513 // Previous values
514 LexicalScope* lexical_scope_parent_;
515 Scope* previous_scope_;
516 int previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100517 unsigned previous_ast_node_id_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000518};
519
Steve Block44f0eee2011-05-26 01:26:41 +0100520
521LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
522 : materialized_literal_count_(0),
523 expected_property_count_(0),
524 only_simple_this_property_assignments_(false),
525 this_property_assignments_(isolate->factory()->empty_fixed_array()),
Steve Block44f0eee2011-05-26 01:26:41 +0100526 parser_(parser),
527 lexical_scope_parent_(parser->lexical_scope_),
528 previous_scope_(parser->top_scope_),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100529 previous_with_nesting_level_(parser->with_nesting_level_),
530 previous_ast_node_id_(isolate->ast_node_id()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100531 parser->top_scope_ = scope;
532 parser->lexical_scope_ = this;
533 parser->with_nesting_level_ = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100534 isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1);
Steve Block44f0eee2011-05-26 01:26:41 +0100535}
536
537
538LexicalScope::~LexicalScope() {
539 parser_->top_scope_->Leave();
540 parser_->top_scope_ = previous_scope_;
541 parser_->lexical_scope_ = lexical_scope_parent_;
542 parser_->with_nesting_level_ = previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100543 parser_->isolate()->set_ast_node_id(previous_ast_node_id_);
Steve Block44f0eee2011-05-26 01:26:41 +0100544}
545
546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547// ----------------------------------------------------------------------------
548// The CHECK_OK macro is a convenient macro to enforce error
549// handling for functions that may fail (by returning !*ok).
550//
551// CAUTION: This macro appends extra statements after a call,
552// thus it must never be used where only a single statement
553// is correct (e.g. an if statement branch w/o braces)!
554
555#define CHECK_OK ok); \
556 if (!*ok) return NULL; \
557 ((void)0
558#define DUMMY ) // to make indentation work
559#undef DUMMY
560
561#define CHECK_FAILED /**/); \
562 if (failed_) return NULL; \
563 ((void)0
564#define DUMMY ) // to make indentation work
565#undef DUMMY
566
567// ----------------------------------------------------------------------------
568// Implementation of Parser
569
570Parser::Parser(Handle<Script> script,
571 bool allow_natives_syntax,
572 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000573 ScriptDataImpl* pre_data)
Steve Block44f0eee2011-05-26 01:26:41 +0100574 : isolate_(script->GetIsolate()),
575 symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800576 script_(script),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100577 scanner_(isolate_->unicode_cache()),
Steve Blocka7e24c12009-10-30 11:49:00 +0000578 top_scope_(NULL),
579 with_nesting_level_(0),
Steve Block44f0eee2011-05-26 01:26:41 +0100580 lexical_scope_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000581 target_stack_(NULL),
582 allow_natives_syntax_(allow_natives_syntax),
583 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100584 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100585 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100586 stack_overflow_(false),
587 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100588 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000589}
590
591
Steve Blocka7e24c12009-10-30 11:49:00 +0000592FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Block1e0659c2011-05-24 12:43:12 +0100593 bool in_global_context,
594 StrictModeFlag strict_mode) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000595 CompilationZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000596
Steve Block44f0eee2011-05-26 01:26:41 +0100597 HistogramTimerScope timer(isolate()->counters()->parse());
598 isolate()->counters()->total_parse_size()->Increment(source->length());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100599 fni_ = new(zone()) FuncNameInferrer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000600
601 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100602 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100603 if (source->IsExternalTwoByteString()) {
604 // Notice that the stream is destroyed at the end of the branch block.
605 // The last line of the blocks can't be moved outside, even though they're
606 // identical calls.
607 ExternalTwoByteStringUC16CharacterStream stream(
608 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100609 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100610 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100611 } else {
612 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100613 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100614 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100615 }
616}
617
618
619FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
620 bool in_global_context,
Steve Block1e0659c2011-05-24 12:43:12 +0100621 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100622 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000623 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100624 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000625
626 // Compute the parsing mode.
627 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
628 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
629
630 Scope::Type type =
631 in_global_context
632 ? Scope::GLOBAL_SCOPE
633 : Scope::EVAL_SCOPE;
Steve Block44f0eee2011-05-26 01:26:41 +0100634 Handle<String> no_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000635
636 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800637 { Scope* scope = NewScope(top_scope_, type, inside_with());
Steve Block44f0eee2011-05-26 01:26:41 +0100638 LexicalScope lexical_scope(this, scope, isolate());
Steve Block1e0659c2011-05-24 12:43:12 +0100639 if (strict_mode == kStrictMode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100640 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100641 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000642 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000643 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100644 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800645 ParseSourceElements(body, Token::EOS, &ok);
Steve Block44f0eee2011-05-26 01:26:41 +0100646 if (ok && top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100647 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
648 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 if (ok) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100650 result = new(zone()) FunctionLiteral(
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 no_name,
652 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800653 body,
Steve Block44f0eee2011-05-26 01:26:41 +0100654 lexical_scope.materialized_literal_count(),
655 lexical_scope.expected_property_count(),
656 lexical_scope.only_simple_this_property_assignments(),
657 lexical_scope.this_property_assignments(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000658 0,
659 0,
660 source->length(),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100661 false);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100662 } else if (stack_overflow_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100663 isolate()->StackOverflow();
Steve Blocka7e24c12009-10-30 11:49:00 +0000664 }
665 }
666
667 // Make sure the target stack is empty.
668 ASSERT(target_stack_ == NULL);
669
670 // If there was a syntax error we have to get rid of the AST
671 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000673 return result;
674}
675
Steve Block44f0eee2011-05-26 01:26:41 +0100676FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000677 CompilationZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Block44f0eee2011-05-26 01:26:41 +0100678 HistogramTimerScope timer(isolate()->counters()->parse_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100679 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100680 isolate()->counters()->total_parse_size()->Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000681
Steve Block44f0eee2011-05-26 01:26:41 +0100682 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100683 // Initialize parser state.
684 source->TryFlatten();
685 if (source->IsExternalTwoByteString()) {
686 ExternalTwoByteStringUC16CharacterStream stream(
687 Handle<ExternalTwoByteString>::cast(source),
Steve Block44f0eee2011-05-26 01:26:41 +0100688 shared_info->start_position(),
689 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100690 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
691 return result;
692 } else {
693 GenericStringUC16CharacterStream stream(source,
Steve Block44f0eee2011-05-26 01:26:41 +0100694 shared_info->start_position(),
695 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100696 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
697 return result;
698 }
699}
700
701
Steve Block44f0eee2011-05-26 01:26:41 +0100702FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100703 UC16CharacterStream* source,
704 ZoneScope* zone_scope) {
Steve Block44f0eee2011-05-26 01:26:41 +0100705 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Steve Block9fac8402011-05-12 15:51:54 +0100706 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100707 ASSERT(target_stack_ == NULL);
708
Steve Block44f0eee2011-05-26 01:26:41 +0100709 Handle<String> name(String::cast(shared_info->name()));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100710 fni_ = new(zone()) FuncNameInferrer();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100711 fni_->PushEnclosingName(name);
712
Steve Blocka7e24c12009-10-30 11:49:00 +0000713 mode_ = PARSE_EAGERLY;
714
715 // Place holder for the result.
716 FunctionLiteral* result = NULL;
717
718 {
719 // Parse the function literal.
Steve Block44f0eee2011-05-26 01:26:41 +0100720 Handle<String> no_name = isolate()->factory()->empty_symbol();
721 Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
722 if (!info->closure().is_null()) {
723 scope = Scope::DeserializeScopeChain(info, scope);
724 }
725 LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000726
Steve Block44f0eee2011-05-26 01:26:41 +0100727 if (shared_info->strict_mode()) {
728 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100729 }
730
Ben Murdochf87a2032010-10-22 12:50:53 +0100731 FunctionLiteralType type =
Steve Block44f0eee2011-05-26 01:26:41 +0100732 shared_info->is_expression() ? EXPRESSION : DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000733 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100734 result = ParseFunctionLiteral(name,
735 false, // Strict mode name already checked.
736 RelocInfo::kNoPosition, type, &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000737 // Make sure the results agree.
738 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000739 }
740
741 // Make sure the target stack is empty.
742 ASSERT(target_stack_ == NULL);
743
744 // If there was a stack overflow we have to get rid of AST and it is
745 // not safe to do before scope has been deleted.
746 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100747 zone_scope->DeleteOnExit();
Steve Block44f0eee2011-05-26 01:26:41 +0100748 if (stack_overflow_) isolate()->StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100749 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100750 Handle<String> inferred_name(shared_info->inferred_name());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100751 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000752 }
753 return result;
754}
755
Ben Murdochf87a2032010-10-22 12:50:53 +0100756
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800757Handle<String> Parser::GetSymbol(bool* ok) {
758 int symbol_id = -1;
759 if (pre_data() != NULL) {
760 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000761 }
Steve Block9fac8402011-05-12 15:51:54 +0100762 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000763}
Steve Blocka7e24c12009-10-30 11:49:00 +0000764
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800765
Steve Blocka7e24c12009-10-30 11:49:00 +0000766void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100767 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000768 ReportMessageAt(source_location, type, args);
769}
770
771
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800772void Parser::ReportMessageAt(Scanner::Location source_location,
773 const char* type,
774 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000775 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100776 source_location.beg_pos,
777 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100778 Factory* factory = isolate()->factory();
779 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 for (int i = 0; i < args.length(); i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100781 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100782 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000783 }
Steve Block44f0eee2011-05-26 01:26:41 +0100784 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
785 Handle<Object> result = factory->NewSyntaxError(type, array);
786 isolate()->Throw(*result, &location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000787}
788
789
Ben Murdochb8e0da22011-05-16 14:20:40 +0100790void Parser::ReportMessageAt(Scanner::Location source_location,
791 const char* type,
792 Vector<Handle<String> > args) {
793 MessageLocation location(script_,
794 source_location.beg_pos,
795 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100796 Factory* factory = isolate()->factory();
797 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100798 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100799 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100800 }
Steve Block44f0eee2011-05-26 01:26:41 +0100801 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
802 Handle<Object> result = factory->NewSyntaxError(type, array);
803 isolate()->Throw(*result, &location);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100804}
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:
Steve Block44f0eee2011-05-26 01:26:41 +0100928 explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate)
929 : isolate_(isolate),
930 only_simple_this_property_assignments_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 names_(NULL),
932 assigned_arguments_(NULL),
933 assigned_constants_(NULL) {}
934
935 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000936 // Bail out if function already has property assignment that are
937 // not simple this property assignments.
938 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000939 return;
940 }
941
942 // Check whether this statement is of the form this.x = ...;
943 Assignment* assignment = AsAssignment(stat);
944 if (IsThisPropertyAssignment(assignment)) {
945 HandleThisPropertyAssignment(scope, assignment);
946 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000947 only_simple_this_property_assignments_ = false;
948 }
949 }
950
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 // Returns whether only statements of the form this.x = y; where y is either a
952 // constant or a function argument was encountered.
953 bool only_simple_this_property_assignments() {
954 return only_simple_this_property_assignments_;
955 }
956
957 // Returns a fixed array containing three elements for each assignment of the
958 // form this.x = y;
959 Handle<FixedArray> GetThisPropertyAssignments() {
960 if (names_ == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100961 return isolate_->factory()->empty_fixed_array();
Steve Blocka7e24c12009-10-30 11:49:00 +0000962 }
963 ASSERT(names_ != NULL);
964 ASSERT(assigned_arguments_ != NULL);
965 ASSERT_EQ(names_->length(), assigned_arguments_->length());
966 ASSERT_EQ(names_->length(), assigned_constants_->length());
967 Handle<FixedArray> assignments =
Steve Block44f0eee2011-05-26 01:26:41 +0100968 isolate_->factory()->NewFixedArray(names_->length() * 3);
Steve Blocka7e24c12009-10-30 11:49:00 +0000969 for (int i = 0; i < names_->length(); i++) {
970 assignments->set(i * 3, *names_->at(i));
971 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
972 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
973 }
974 return assignments;
975 }
976
977 private:
978 bool IsThisPropertyAssignment(Assignment* assignment) {
979 if (assignment != NULL) {
980 Property* property = assignment->target()->AsProperty();
981 return assignment->op() == Token::ASSIGN
982 && property != NULL
983 && property->obj()->AsVariableProxy() != NULL
984 && property->obj()->AsVariableProxy()->is_this();
985 }
986 return false;
987 }
988
989 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +0100990 // Check that the property assigned to is a named property, which is not
991 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +0000992 Property* property = assignment->target()->AsProperty();
993 ASSERT(property != NULL);
994 Literal* literal = property->key()->AsLiteral();
995 uint32_t dummy;
996 if (literal != NULL &&
997 literal->handle()->IsString() &&
Steve Block44f0eee2011-05-26 01:26:41 +0100998 !String::cast(*(literal->handle()))->Equals(
999 isolate_->heap()->Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001000 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1001 Handle<String> key = Handle<String>::cast(literal->handle());
1002
1003 // Check whether the value assigned is either a constant or matches the
1004 // name of one of the arguments to the function.
1005 if (assignment->value()->AsLiteral() != NULL) {
1006 // Constant assigned.
1007 Literal* literal = assignment->value()->AsLiteral();
1008 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001009 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001010 } else if (assignment->value()->AsVariableProxy() != NULL) {
1011 // Variable assigned.
1012 Handle<String> name =
1013 assignment->value()->AsVariableProxy()->name();
1014 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001015 for (int i = 0; i < scope->num_parameters(); i++) {
1016 if (*scope->parameter(i)->name() == *name) {
1017 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001018 AssignmentFromParameter(key, i);
1019 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001020 }
1021 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001022 }
1023 }
Steve Blockd0582a62009-12-15 09:54:21 +00001024 // It is not a simple "this.x = value;" assignment with a constant
1025 // or parameter value.
1026 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001027 }
1028
1029 void AssignmentFromParameter(Handle<String> name, int index) {
1030 EnsureAllocation();
1031 names_->Add(name);
1032 assigned_arguments_->Add(index);
Steve Block44f0eee2011-05-26 01:26:41 +01001033 assigned_constants_->Add(isolate_->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001034 }
1035
1036 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
1037 EnsureAllocation();
1038 names_->Add(name);
1039 assigned_arguments_->Add(-1);
1040 assigned_constants_->Add(value);
1041 }
1042
Steve Blockd0582a62009-12-15 09:54:21 +00001043 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001044 // The this assignment is not a simple one.
1045 only_simple_this_property_assignments_ = false;
1046 }
1047
1048 void EnsureAllocation() {
1049 if (names_ == NULL) {
1050 ASSERT(assigned_arguments_ == NULL);
1051 ASSERT(assigned_constants_ == NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +00001052 Zone* zone = isolate_->zone();
1053 names_ = new(zone) ZoneStringList(4);
1054 assigned_arguments_ = new(zone) ZoneList<int>(4);
1055 assigned_constants_ = new(zone) ZoneObjectList(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001056 }
1057 }
1058
Steve Block44f0eee2011-05-26 01:26:41 +01001059 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001060 bool only_simple_this_property_assignments_;
1061 ZoneStringList* names_;
1062 ZoneList<int>* assigned_arguments_;
1063 ZoneObjectList* assigned_constants_;
1064};
1065
1066
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001067void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001068 int end_token,
1069 bool* ok) {
1070 // SourceElements ::
1071 // (Statement)* <end_token>
1072
1073 // Allocate a target stack to use for this set of source
1074 // elements. This way, all scripts and functions get their own
1075 // target stack thus avoiding illegal breaks and continues across
1076 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001077 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001078
1079 ASSERT(processor != NULL);
1080 InitializationBlockFinder block_finder;
Steve Block44f0eee2011-05-26 01:26:41 +01001081 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
Steve Block1e0659c2011-05-24 12:43:12 +01001082 bool directive_prologue = true; // Parsing directive prologue.
1083
Steve Blocka7e24c12009-10-30 11:49:00 +00001084 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001085 if (directive_prologue && peek() != Token::STRING) {
1086 directive_prologue = false;
1087 }
1088
1089 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001090
1091 Statement* stat;
1092 if (peek() == Token::FUNCTION) {
1093 // FunctionDeclaration is only allowed in the context of SourceElements
1094 // (Ecma 262 5th Edition, clause 14):
1095 // SourceElement:
1096 // Statement
1097 // FunctionDeclaration
1098 // Common language extension is to allow function declaration in place
1099 // of any statement. This language extension is disabled in strict mode.
1100 stat = ParseFunctionDeclaration(CHECK_OK);
1101 } else {
1102 stat = ParseStatement(NULL, CHECK_OK);
1103 }
Steve Block1e0659c2011-05-24 12:43:12 +01001104
1105 if (stat == NULL || stat->IsEmpty()) {
1106 directive_prologue = false; // End of directive prologue.
1107 continue;
1108 }
1109
1110 if (directive_prologue) {
1111 // A shot at a directive.
1112 ExpressionStatement *e_stat;
1113 Literal *literal;
1114 // Still processing directive prologue?
1115 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1116 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1117 literal->handle()->IsString()) {
1118 Handle<String> directive = Handle<String>::cast(literal->handle());
1119
1120 // Check "use strict" directive (ES5 14.1).
Steve Block44f0eee2011-05-26 01:26:41 +01001121 if (!top_scope_->is_strict_mode() &&
1122 directive->Equals(isolate()->heap()->use_strict()) &&
Steve Block1e0659c2011-05-24 12:43:12 +01001123 token_loc.end_pos - token_loc.beg_pos ==
Steve Block44f0eee2011-05-26 01:26:41 +01001124 isolate()->heap()->use_strict()->length() + 2) {
1125 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +01001126 // "use strict" is the only directive for now.
1127 directive_prologue = false;
1128 }
1129 } else {
1130 // End of the directive prologue.
1131 directive_prologue = false;
1132 }
1133 }
1134
Steve Blocka7e24c12009-10-30 11:49:00 +00001135 // We find and mark the initialization blocks on top level code only.
1136 // This is because the optimization prevents reuse of the map transitions,
1137 // so it should be used only for code that will only be run once.
1138 if (top_scope_->is_global_scope()) {
1139 block_finder.Update(stat);
1140 }
1141 // Find and mark all assignments to named properties in this (this.x =)
1142 if (top_scope_->is_function_scope()) {
1143 this_property_assignment_finder.Update(top_scope_, stat);
1144 }
1145 processor->Add(stat);
1146 }
1147
1148 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001149 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001150 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001151 this_property_assignment_finder.only_simple_this_property_assignments()
1152 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001153 if (only_simple_this_property_assignments) {
Steve Block44f0eee2011-05-26 01:26:41 +01001154 lexical_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001155 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001156 this_property_assignment_finder.GetThisPropertyAssignments());
1157 }
1158 }
1159 return 0;
1160}
1161
1162
1163Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1164 // Statement ::
1165 // Block
1166 // VariableStatement
1167 // EmptyStatement
1168 // ExpressionStatement
1169 // IfStatement
1170 // IterationStatement
1171 // ContinueStatement
1172 // BreakStatement
1173 // ReturnStatement
1174 // WithStatement
1175 // LabelledStatement
1176 // SwitchStatement
1177 // ThrowStatement
1178 // TryStatement
1179 // DebuggerStatement
1180
1181 // Note: Since labels can only be used by 'break' and 'continue'
1182 // statements, which themselves are only valid within blocks,
1183 // iterations or 'switch' statements (i.e., BreakableStatements),
1184 // labels can be simply ignored in all other cases; except for
1185 // trivial labeled break statements 'label: break label' which is
1186 // parsed into an empty statement.
1187
1188 // Keep the source position of the statement
1189 int statement_pos = scanner().peek_location().beg_pos;
1190 Statement* stmt = NULL;
1191 switch (peek()) {
1192 case Token::LBRACE:
1193 return ParseBlock(labels, ok);
1194
1195 case Token::CONST: // fall through
1196 case Token::VAR:
1197 stmt = ParseVariableStatement(ok);
1198 break;
1199
1200 case Token::SEMICOLON:
1201 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001202 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001203
1204 case Token::IF:
1205 stmt = ParseIfStatement(labels, ok);
1206 break;
1207
1208 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001209 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001210 break;
1211
1212 case Token::WHILE:
1213 stmt = ParseWhileStatement(labels, ok);
1214 break;
1215
1216 case Token::FOR:
1217 stmt = ParseForStatement(labels, ok);
1218 break;
1219
1220 case Token::CONTINUE:
1221 stmt = ParseContinueStatement(ok);
1222 break;
1223
1224 case Token::BREAK:
1225 stmt = ParseBreakStatement(labels, ok);
1226 break;
1227
1228 case Token::RETURN:
1229 stmt = ParseReturnStatement(ok);
1230 break;
1231
1232 case Token::WITH:
1233 stmt = ParseWithStatement(labels, ok);
1234 break;
1235
1236 case Token::SWITCH:
1237 stmt = ParseSwitchStatement(labels, ok);
1238 break;
1239
1240 case Token::THROW:
1241 stmt = ParseThrowStatement(ok);
1242 break;
1243
1244 case Token::TRY: {
1245 // NOTE: It is somewhat complicated to have labels on
1246 // try-statements. When breaking out of a try-finally statement,
1247 // one must take great care not to treat it as a
1248 // fall-through. It is much easier just to wrap the entire
1249 // try-statement in a statement block and put the labels there
Ben Murdoch8b112d22011-06-08 16:22:53 +01001250 Block* result = new(zone()) Block(labels, 1, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001251 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 TryStatement* statement = ParseTryStatement(CHECK_OK);
1253 if (statement) {
1254 statement->set_statement_pos(statement_pos);
1255 }
1256 if (result) result->AddStatement(statement);
1257 return result;
1258 }
1259
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001260 case Token::FUNCTION: {
1261 // In strict mode, FunctionDeclaration is only allowed in the context
1262 // of SourceElements.
Steve Block44f0eee2011-05-26 01:26:41 +01001263 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001264 ReportMessageAt(scanner().peek_location(), "strict_function",
1265 Vector<const char*>::empty());
1266 *ok = false;
1267 return NULL;
1268 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001269 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001270 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001271
1272 case Token::NATIVE:
1273 return ParseNativeDeclaration(ok);
1274
1275 case Token::DEBUGGER:
1276 stmt = ParseDebuggerStatement(ok);
1277 break;
1278
1279 default:
1280 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1281 }
1282
1283 // Store the source position of the statement
1284 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1285 return stmt;
1286}
1287
1288
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001289VariableProxy* Parser::Declare(Handle<String> name,
1290 Variable::Mode mode,
1291 FunctionLiteral* fun,
1292 bool resolve,
1293 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001294 Variable* var = NULL;
1295 // If we are inside a function, a declaration of a variable
1296 // is a truly local variable, and the scope of the variable
1297 // is always the function scope.
1298
1299 // If a function scope exists, then we can statically declare this
1300 // variable and also set its mode. In any case, a Declaration node
1301 // will be added to the scope so that the declaration can be added
1302 // to the corresponding activation frame at runtime if necessary.
1303 // For instance declarations inside an eval scope need to be added
1304 // to the calling function context.
Ben Murdoch257744e2011-11-30 15:57:28 +00001305 // Similarly, strict mode eval scope does not leak variable declarations to
1306 // the caller's scope so we declare all locals, too.
1307 if (top_scope_->is_function_scope() ||
1308 top_scope_->is_strict_mode_eval_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001309 // Declare the variable in the function scope.
1310 var = top_scope_->LocalLookup(name);
1311 if (var == NULL) {
1312 // Declare the name.
Steve Block053d10c2011-06-13 19:13:29 +01001313 var = top_scope_->DeclareLocal(name, mode, Scope::VAR_OR_CONST);
Steve Blocka7e24c12009-10-30 11:49:00 +00001314 } else {
1315 // The name was declared before; check for conflicting
1316 // re-declarations. If the previous declaration was a const or the
1317 // current declaration is a const then we have a conflict. There is
1318 // similar code in runtime.cc in the Declare functions.
1319 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1320 // We only have vars and consts in declarations.
1321 ASSERT(var->mode() == Variable::VAR ||
1322 var->mode() == Variable::CONST);
1323 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1324 Handle<String> type_string =
Steve Block44f0eee2011-05-26 01:26:41 +01001325 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001326 Expression* expression =
Steve Block44f0eee2011-05-26 01:26:41 +01001327 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00001328 type_string, name);
1329 top_scope_->SetIllegalRedeclaration(expression);
1330 }
1331 }
1332 }
1333
1334 // We add a declaration node for every declaration. The compiler
1335 // will only generate code if necessary. In particular, declarations
1336 // for inner local variables that do not represent functions won't
1337 // result in any generated code.
1338 //
1339 // Note that we always add an unresolved proxy even if it's not
1340 // used, simply because we don't know in this method (w/o extra
1341 // parameters) if the proxy is needed or not. The proxy will be
1342 // bound during variable resolution time unless it was pre-bound
1343 // below.
1344 //
1345 // WARNING: This will lead to multiple declaration nodes for the
1346 // same variable if it is declared several times. This is not a
1347 // semantic issue as long as we keep the source order, but it may be
1348 // a performance issue since it may lead to repeated
1349 // Runtime::DeclareContextSlot() calls.
1350 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001351 top_scope_->AddDeclaration(new(zone()) Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001352
1353 // For global const variables we bind the proxy to a variable.
1354 if (mode == Variable::CONST && top_scope_->is_global_scope()) {
1355 ASSERT(resolve); // should be set by all callers
1356 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001357 var = new(zone()) Variable(top_scope_, name, Variable::CONST, true, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001358 }
1359
1360 // If requested and we have a local variable, bind the proxy to the variable
1361 // at parse-time. This is used for functions (and consts) declared inside
1362 // statements: the corresponding function (or const) variable must be in the
1363 // function scope and not a statement-local scope, e.g. as provided with a
1364 // 'with' statement:
1365 //
1366 // with (obj) {
1367 // function f() {}
1368 // }
1369 //
1370 // which is translated into:
1371 //
1372 // with (obj) {
1373 // // in this case this is not: 'var f; f = function () {};'
1374 // var f = function () {};
1375 // }
1376 //
1377 // Note that if 'f' is accessed from inside the 'with' statement, it
1378 // will be allocated in the context (because we must be able to look
1379 // it up dynamically) but it will also be accessed statically, i.e.,
1380 // with a context slot index and a context chain length for this
1381 // initialization code. Thus, inside the 'with' statement, we need
1382 // both access to the static and the dynamic context chain; the
1383 // runtime needs to provide both.
1384 if (resolve && var != NULL) proxy->BindTo(var);
1385
1386 return proxy;
1387}
1388
1389
1390// Language extension which is only enabled for source files loaded
1391// through the API's extension mechanism. A native function
1392// declaration is resolved by looking up the function through a
1393// callback provided by the extension.
1394Statement* Parser::ParseNativeDeclaration(bool* ok) {
1395 if (extension_ == NULL) {
1396 ReportUnexpectedToken(Token::NATIVE);
1397 *ok = false;
1398 return NULL;
1399 }
1400
1401 Expect(Token::NATIVE, CHECK_OK);
1402 Expect(Token::FUNCTION, CHECK_OK);
1403 Handle<String> name = ParseIdentifier(CHECK_OK);
1404 Expect(Token::LPAREN, CHECK_OK);
1405 bool done = (peek() == Token::RPAREN);
1406 while (!done) {
1407 ParseIdentifier(CHECK_OK);
1408 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001409 if (!done) {
1410 Expect(Token::COMMA, CHECK_OK);
1411 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001412 }
1413 Expect(Token::RPAREN, CHECK_OK);
1414 Expect(Token::SEMICOLON, CHECK_OK);
1415
Steve Blocka7e24c12009-10-30 11:49:00 +00001416 // Make sure that the function containing the native declaration
1417 // isn't lazily compiled. The extension structures are only
1418 // accessible while parsing the first time not when reparsing
1419 // because of lazy compilation.
1420 top_scope_->ForceEagerCompilation();
1421
1422 // Compute the function template for the native function.
1423 v8::Handle<v8::FunctionTemplate> fun_template =
1424 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1425 ASSERT(!fun_template.IsEmpty());
1426
Steve Block6ded16b2010-05-10 14:33:55 +01001427 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001428 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1429 const int literals = fun->NumberOfLiterals();
1430 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001431 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001432 Handle<SharedFunctionInfo> shared =
Steve Block44f0eee2011-05-26 01:26:41 +01001433 isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001434 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001435 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001436
Steve Block6ded16b2010-05-10 14:33:55 +01001437 // Copy the function data to the shared function info.
1438 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001439 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001440 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001441
1442 // TODO(1240846): It's weird that native function declarations are
1443 // introduced dynamically when we meet their declarations, whereas
1444 // other functions are setup when entering the surrounding scope.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001445 SharedFunctionInfoLiteral* lit =
1446 new(zone()) SharedFunctionInfoLiteral(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001447 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001448 return new(zone()) ExpressionStatement(new(zone()) Assignment(
1449 Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001450}
1451
1452
1453Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1454 // FunctionDeclaration ::
1455 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1456 Expect(Token::FUNCTION, CHECK_OK);
1457 int function_token_position = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01001458 bool is_reserved = false;
1459 Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001460 FunctionLiteral* fun = ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01001461 is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001462 function_token_position,
1463 DECLARATION,
1464 CHECK_OK);
1465 // Even if we're not at the top-level of the global or a function
1466 // scope, we treat is as such and introduce the function with it's
1467 // initial value upon entering the corresponding scope.
1468 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001469 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001470}
1471
1472
1473Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1474 // Block ::
1475 // '{' Statement* '}'
1476
1477 // Note that a Block does not introduce a new execution scope!
1478 // (ECMA-262, 3rd, 12.2)
1479 //
1480 // Construct block expecting 16 statements.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001481 Block* result = new(zone()) Block(labels, 16, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001482 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001483 Expect(Token::LBRACE, CHECK_OK);
1484 while (peek() != Token::RBRACE) {
1485 Statement* stat = ParseStatement(NULL, CHECK_OK);
1486 if (stat && !stat->IsEmpty()) result->AddStatement(stat);
1487 }
1488 Expect(Token::RBRACE, CHECK_OK);
1489 return result;
1490}
1491
1492
1493Block* Parser::ParseVariableStatement(bool* ok) {
1494 // VariableStatement ::
1495 // VariableDeclarations ';'
1496
1497 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature
1498 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK);
1499 ExpectSemicolon(CHECK_OK);
1500 return result;
1501}
1502
Steve Block44f0eee2011-05-26 01:26:41 +01001503
1504bool Parser::IsEvalOrArguments(Handle<String> string) {
1505 return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
1506 string.is_identical_to(isolate()->factory()->arguments_symbol());
Steve Block1e0659c2011-05-24 12:43:12 +01001507}
Steve Blocka7e24c12009-10-30 11:49:00 +00001508
Steve Block44f0eee2011-05-26 01:26:41 +01001509
Steve Blocka7e24c12009-10-30 11:49:00 +00001510// If the variable declaration declares exactly one non-const
1511// variable, then *var is set to that variable. In all other cases,
1512// *var is untouched; in particular, it is the caller's responsibility
1513// to initialize it properly. This mechanism is used for the parsing
1514// of 'for-in' loops.
1515Block* Parser::ParseVariableDeclarations(bool accept_IN,
1516 Expression** var,
1517 bool* ok) {
1518 // VariableDeclarations ::
1519 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1520
1521 Variable::Mode mode = Variable::VAR;
1522 bool is_const = false;
1523 if (peek() == Token::VAR) {
1524 Consume(Token::VAR);
1525 } else if (peek() == Token::CONST) {
1526 Consume(Token::CONST);
Steve Block44f0eee2011-05-26 01:26:41 +01001527 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001528 ReportMessage("strict_const", Vector<const char*>::empty());
1529 *ok = false;
1530 return NULL;
1531 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001532 mode = Variable::CONST;
1533 is_const = true;
1534 } else {
1535 UNREACHABLE(); // by current callers
1536 }
1537
1538 // The scope of a variable/const declared anywhere inside a function
1539 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1540 // transform a source-level variable/const declaration into a (Function)
1541 // Scope declaration, and rewrite the source-level initialization into an
1542 // assignment statement. We use a block to collect multiple assignments.
1543 //
1544 // We mark the block as initializer block because we don't want the
1545 // rewriter to add a '.result' assignment to such a block (to get compliant
1546 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1547 // reasons when pretty-printing. Also, unless an assignment (initialization)
1548 // is inside an initializer block, it is ignored.
1549 //
1550 // Create new block with one expected declaration.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001551 Block* block = new(zone()) Block(NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001552 VariableProxy* last_var = NULL; // the last variable declared
1553 int nvars = 0; // the number of variables declared
1554 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001555 if (fni_ != NULL) fni_->Enter();
1556
Steve Blocka7e24c12009-10-30 11:49:00 +00001557 // Parse variable name.
1558 if (nvars > 0) Consume(Token::COMMA);
1559 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001560 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001561
Steve Block1e0659c2011-05-24 12:43:12 +01001562 // Strict mode variables may not be named eval or arguments
Steve Block44f0eee2011-05-26 01:26:41 +01001563 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01001564 ReportMessage("strict_var_name", Vector<const char*>::empty());
1565 *ok = false;
1566 return NULL;
1567 }
1568
Steve Blocka7e24c12009-10-30 11:49:00 +00001569 // Declare variable.
1570 // Note that we *always* must treat the initial value via a separate init
1571 // assignment for variables and constants because the value must be assigned
1572 // when the variable is encountered in the source. But the variable/constant
1573 // is declared (and set to 'undefined') upon entering the function within
1574 // which the variable or constant is declared. Only function variables have
1575 // an initial value in the declaration (because they are initialized upon
1576 // entering the function).
1577 //
1578 // If we have a const declaration, in an inner scope, the proxy is always
1579 // bound to the declared variable (independent of possibly surrounding with
1580 // statements).
1581 last_var = Declare(name, mode, NULL,
1582 is_const /* always bound for CONST! */,
1583 CHECK_OK);
1584 nvars++;
Steve Block053d10c2011-06-13 19:13:29 +01001585 if (top_scope_->num_var_or_const() > kMaxNumFunctionLocals) {
1586 ReportMessageAt(scanner().location(), "too_many_variables",
1587 Vector<const char*>::empty());
1588 *ok = false;
1589 return NULL;
1590 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001591
1592 // Parse initialization expression if present and/or needed. A
1593 // declaration of the form:
1594 //
1595 // var v = x;
1596 //
1597 // is syntactic sugar for:
1598 //
1599 // var v; v = x;
1600 //
1601 // In particular, we need to re-lookup 'v' as it may be a
1602 // different 'v' than the 'v' in the declaration (if we are inside
1603 // a 'with' statement that makes a object property with name 'v'
1604 // visible).
1605 //
1606 // However, note that const declarations are different! A const
1607 // declaration of the form:
1608 //
1609 // const c = x;
1610 //
1611 // is *not* syntactic sugar for:
1612 //
1613 // const c; c = x;
1614 //
1615 // The "variable" c initialized to x is the same as the declared
1616 // one - there is no re-lookup (see the last parameter of the
1617 // Declare() call above).
1618
1619 Expression* value = NULL;
1620 int position = -1;
1621 if (peek() == Token::ASSIGN) {
1622 Expect(Token::ASSIGN, CHECK_OK);
1623 position = scanner().location().beg_pos;
1624 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001625 // Don't infer if it is "a = function(){...}();"-like expression.
1626 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer();
Steve Blocka7e24c12009-10-30 11:49:00 +00001627 }
1628
1629 // Make sure that 'const c' actually initializes 'c' to undefined
1630 // even though it seems like a stupid thing to do.
1631 if (value == NULL && is_const) {
1632 value = GetLiteralUndefined();
1633 }
1634
1635 // Global variable declarations must be compiled in a specific
1636 // way. When the script containing the global variable declaration
1637 // is entered, the global variable must be declared, so that if it
1638 // doesn't exist (not even in a prototype of the global object) it
1639 // gets created with an initial undefined value. This is handled
1640 // by the declarations part of the function representing the
1641 // top-level global code; see Runtime::DeclareGlobalVariable. If
1642 // it already exists (in the object or in a prototype), it is
1643 // *not* touched until the variable declaration statement is
1644 // executed.
1645 //
1646 // Executing the variable declaration statement will always
1647 // guarantee to give the global object a "local" variable; a
1648 // variable defined in the global object and not in any
1649 // prototype. This way, global variable declarations can shadow
1650 // properties in the prototype chain, but only after the variable
1651 // declaration statement has been executed. This is important in
1652 // browsers where the global object (window) has lots of
1653 // properties defined in prototype objects.
1654
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001655 if (top_scope_->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001656 // Compute the arguments for the runtime call.
Ben Murdoch257744e2011-11-30 15:57:28 +00001657 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001658 // We have at least 1 parameter.
1659 arguments->Add(new(zone()) Literal(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001660 CallRuntime* initialize;
1661
1662 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001663 arguments->Add(value);
1664 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001665
1666 // Construct the call to Runtime_InitializeConstGlobal
1667 // and add it to the initialization statement block.
1668 // Note that the function does different things depending on
1669 // the number of arguments (1 or 2).
Steve Blocka7e24c12009-10-30 11:49:00 +00001670 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001671 new(zone()) CallRuntime(
Steve Block44f0eee2011-05-26 01:26:41 +01001672 isolate()->factory()->InitializeConstGlobal_symbol(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001673 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1674 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001675 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001676 // Add strict mode.
1677 // We may want to pass singleton to avoid Literal allocations.
1678 arguments->Add(NewNumberLiteral(
Steve Block44f0eee2011-05-26 01:26:41 +01001679 top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001680
1681 // Be careful not to assign a value to the global variable if
1682 // we're in a with. The initialization value should not
1683 // necessarily be stored in the global object in that case,
1684 // which is why we need to generate a separate assignment node.
1685 if (value != NULL && !inside_with()) {
1686 arguments->Add(value);
1687 value = NULL; // zap the value to avoid the unnecessary assignment
1688 }
1689
1690 // Construct the call to Runtime_InitializeVarGlobal
1691 // and add it to the initialization statement block.
1692 // Note that the function does different things depending on
1693 // the number of arguments (2 or 3).
Steve Blocka7e24c12009-10-30 11:49:00 +00001694 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001695 new(zone()) CallRuntime(
Steve Block44f0eee2011-05-26 01:26:41 +01001696 isolate()->factory()->InitializeVarGlobal_symbol(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001697 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1698 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001699 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001700
Ben Murdoch8b112d22011-06-08 16:22:53 +01001701 block->AddStatement(new(zone()) ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001702 }
1703
1704 // Add an assignment node to the initialization statement block if
1705 // we still have a pending initialization value. We must distinguish
1706 // between variables and constants: Variable initializations are simply
1707 // assignments (with all the consequences if they are inside a 'with'
1708 // statement - they may change a 'with' object property). Constant
1709 // initializations always assign to the declared constant which is
1710 // always at the function scope level. This is only relevant for
1711 // dynamically looked-up variables and constants (the start context
1712 // for constant lookups is always the function context, while it is
1713 // the top context for variables). Sigh...
1714 if (value != NULL) {
1715 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001716 Assignment* assignment =
1717 new(zone()) Assignment(op, last_var, value, position);
1718 if (block) {
1719 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1720 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001721 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001722
1723 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001724 } while (peek() == Token::COMMA);
1725
1726 if (!is_const && nvars == 1) {
1727 // We have a single, non-const variable.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001728 ASSERT(last_var != NULL);
1729 *var = last_var;
Steve Blocka7e24c12009-10-30 11:49:00 +00001730 }
1731
1732 return block;
1733}
1734
1735
1736static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1737 ASSERT(!label.is_null());
1738 if (labels != NULL)
1739 for (int i = labels->length(); i-- > 0; )
1740 if (labels->at(i).is_identical_to(label))
1741 return true;
1742
1743 return false;
1744}
1745
1746
1747Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1748 bool* ok) {
1749 // ExpressionStatement | LabelledStatement ::
1750 // Expression ';'
1751 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001752 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001753 Expression* expr = ParseExpression(true, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001754 if (peek() == Token::COLON && starts_with_idenfifier && expr &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001755 expr->AsVariableProxy() != NULL &&
1756 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001757 // Expression is a single identifier, and not, e.g., a parenthesized
1758 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001759 VariableProxy* var = expr->AsVariableProxy();
1760 Handle<String> label = var->name();
1761 // TODO(1240780): We don't check for redeclaration of labels
1762 // during preparsing since keeping track of the set of active
1763 // labels requires nontrivial changes to the way scopes are
1764 // structured. However, these are probably changes we want to
1765 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001766 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1767 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1768 const char* elms[2] = { "Label", *c_string };
1769 Vector<const char*> args(elms, 2);
1770 ReportMessage("redeclaration", args);
1771 *ok = false;
1772 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001773 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001774 if (labels == NULL) labels = new(zone()) ZoneStringList(4);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001775 labels->Add(label);
1776 // Remove the "ghost" variable that turned out to be a label
1777 // from the top scope. This way, we don't try to resolve it
1778 // during the scope processing.
1779 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001780 Expect(Token::COLON, CHECK_OK);
1781 return ParseStatement(labels, ok);
1782 }
1783
1784 // Parsed expression statement.
1785 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001786 return new(zone()) ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001787}
1788
1789
1790IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1791 // IfStatement ::
1792 // 'if' '(' Expression ')' Statement ('else' Statement)?
1793
1794 Expect(Token::IF, CHECK_OK);
1795 Expect(Token::LPAREN, CHECK_OK);
1796 Expression* condition = ParseExpression(true, CHECK_OK);
1797 Expect(Token::RPAREN, CHECK_OK);
1798 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1799 Statement* else_statement = NULL;
1800 if (peek() == Token::ELSE) {
1801 Next();
1802 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001803 } else {
1804 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001805 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01001806 return new(zone()) IfStatement(condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001807}
1808
1809
1810Statement* Parser::ParseContinueStatement(bool* ok) {
1811 // ContinueStatement ::
1812 // 'continue' Identifier? ';'
1813
1814 Expect(Token::CONTINUE, CHECK_OK);
1815 Handle<String> label = Handle<String>::null();
1816 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001817 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001818 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1819 label = ParseIdentifier(CHECK_OK);
1820 }
1821 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001822 target = LookupContinueTarget(label, CHECK_OK);
1823 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001824 // Illegal continue statement.
1825 const char* message = "illegal_continue";
1826 Vector<Handle<String> > args;
1827 if (!label.is_null()) {
1828 message = "unknown_label";
1829 args = Vector<Handle<String> >(&label, 1);
1830 }
1831 ReportMessageAt(scanner().location(), message, args);
1832 *ok = false;
1833 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001834 }
1835 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001836 return new(zone()) ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001837}
1838
1839
1840Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1841 // BreakStatement ::
1842 // 'break' Identifier? ';'
1843
1844 Expect(Token::BREAK, CHECK_OK);
1845 Handle<String> label;
1846 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001847 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001848 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1849 label = ParseIdentifier(CHECK_OK);
1850 }
1851 // Parse labeled break statements that target themselves into
1852 // empty statements, e.g. 'l1: l2: l3: break l2;'
1853 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001854 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001855 }
1856 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001857 target = LookupBreakTarget(label, CHECK_OK);
1858 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001859 // Illegal break statement.
1860 const char* message = "illegal_break";
1861 Vector<Handle<String> > args;
1862 if (!label.is_null()) {
1863 message = "unknown_label";
1864 args = Vector<Handle<String> >(&label, 1);
1865 }
1866 ReportMessageAt(scanner().location(), message, args);
1867 *ok = false;
1868 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001869 }
1870 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001871 return new(zone()) BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001872}
1873
1874
1875Statement* Parser::ParseReturnStatement(bool* ok) {
1876 // ReturnStatement ::
1877 // 'return' Expression? ';'
1878
1879 // Consume the return token. It is necessary to do the before
1880 // reporting any errors on it, because of the way errors are
1881 // reported (underlining).
1882 Expect(Token::RETURN, CHECK_OK);
1883
1884 // An ECMAScript program is considered syntactically incorrect if it
1885 // contains a return statement that is not within the body of a
1886 // function. See ECMA-262, section 12.9, page 67.
1887 //
1888 // To be consistent with KJS we report the syntax error at runtime.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001889 if (!top_scope_->is_function_scope()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001890 Handle<String> type = isolate()->factory()->illegal_return_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00001891 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001892 return new(zone()) ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001893 }
1894
1895 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001896 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001897 tok == Token::SEMICOLON ||
1898 tok == Token::RBRACE ||
1899 tok == Token::EOS) {
1900 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001901 return new(zone()) ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001902 }
1903
1904 Expression* expr = ParseExpression(true, CHECK_OK);
1905 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001906 return new(zone()) ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001907}
1908
1909
1910Block* Parser::WithHelper(Expression* obj,
1911 ZoneStringList* labels,
1912 bool is_catch_block,
1913 bool* ok) {
1914 // Parse the statement and collect escaping labels.
Ben Murdoch257744e2011-11-30 15:57:28 +00001915 ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001916 TargetCollector collector(target_list);
1917 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001918 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001919 with_nesting_level_++;
1920 top_scope_->RecordWithStatement();
1921 stat = ParseStatement(labels, CHECK_OK);
1922 with_nesting_level_--;
1923 }
1924 // Create resulting block with two statements.
1925 // 1: Evaluate the with expression.
1926 // 2: The try-finally block evaluating the body.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001927 Block* result = new(zone()) Block(NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001928
1929 if (result != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001930 result->AddStatement(new(zone()) WithEnterStatement(obj, is_catch_block));
Steve Blocka7e24c12009-10-30 11:49:00 +00001931
1932 // Create body block.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001933 Block* body = new(zone()) Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001934 body->AddStatement(stat);
1935
1936 // Create exit block.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001937 Block* exit = new(zone()) Block(NULL, 1, false);
1938 exit->AddStatement(new(zone()) WithExitStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00001939
1940 // Return a try-finally statement.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001941 TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001942 wrapper->set_escaping_targets(collector.targets());
1943 result->AddStatement(wrapper);
1944 }
1945 return result;
1946}
1947
1948
1949Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
1950 // WithStatement ::
1951 // 'with' '(' Expression ')' Statement
1952
1953 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001954
Steve Block44f0eee2011-05-26 01:26:41 +01001955 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001956 ReportMessage("strict_mode_with", Vector<const char*>::empty());
1957 *ok = false;
1958 return NULL;
1959 }
1960
Steve Blocka7e24c12009-10-30 11:49:00 +00001961 Expect(Token::LPAREN, CHECK_OK);
1962 Expression* expr = ParseExpression(true, CHECK_OK);
1963 Expect(Token::RPAREN, CHECK_OK);
1964
1965 return WithHelper(expr, labels, false, CHECK_OK);
1966}
1967
1968
1969CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1970 // CaseClause ::
1971 // 'case' Expression ':' Statement*
1972 // 'default' ':' Statement*
1973
1974 Expression* label = NULL; // NULL expression indicates default case
1975 if (peek() == Token::CASE) {
1976 Expect(Token::CASE, CHECK_OK);
1977 label = ParseExpression(true, CHECK_OK);
1978 } else {
1979 Expect(Token::DEFAULT, CHECK_OK);
1980 if (*default_seen_ptr) {
1981 ReportMessage("multiple_defaults_in_switch",
1982 Vector<const char*>::empty());
1983 *ok = false;
1984 return NULL;
1985 }
1986 *default_seen_ptr = true;
1987 }
1988 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001989 int pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00001990 ZoneList<Statement*>* statements = new(zone()) ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001991 while (peek() != Token::CASE &&
1992 peek() != Token::DEFAULT &&
1993 peek() != Token::RBRACE) {
1994 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001995 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001996 }
1997
Ben Murdoch8b112d22011-06-08 16:22:53 +01001998 return new(zone()) CaseClause(label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001999}
2000
2001
2002SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2003 bool* ok) {
2004 // SwitchStatement ::
2005 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2006
Ben Murdoch8b112d22011-06-08 16:22:53 +01002007 SwitchStatement* statement = new(zone()) SwitchStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002008 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002009
2010 Expect(Token::SWITCH, CHECK_OK);
2011 Expect(Token::LPAREN, CHECK_OK);
2012 Expression* tag = ParseExpression(true, CHECK_OK);
2013 Expect(Token::RPAREN, CHECK_OK);
2014
2015 bool default_seen = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00002016 ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002017 Expect(Token::LBRACE, CHECK_OK);
2018 while (peek() != Token::RBRACE) {
2019 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002020 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002021 }
2022 Expect(Token::RBRACE, CHECK_OK);
2023
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002024 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002025 return statement;
2026}
2027
2028
2029Statement* Parser::ParseThrowStatement(bool* ok) {
2030 // ThrowStatement ::
2031 // 'throw' Expression ';'
2032
2033 Expect(Token::THROW, CHECK_OK);
2034 int pos = scanner().location().beg_pos;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002035 if (scanner().has_line_terminator_before_next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002036 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2037 *ok = false;
2038 return NULL;
2039 }
2040 Expression* exception = ParseExpression(true, CHECK_OK);
2041 ExpectSemicolon(CHECK_OK);
2042
Ben Murdoch8b112d22011-06-08 16:22:53 +01002043 return new(zone()) ExpressionStatement(new(zone()) Throw(exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002044}
2045
2046
2047TryStatement* Parser::ParseTryStatement(bool* ok) {
2048 // TryStatement ::
2049 // 'try' Block Catch
2050 // 'try' Block Finally
2051 // 'try' Block Catch Finally
2052 //
2053 // Catch ::
2054 // 'catch' '(' Identifier ')' Block
2055 //
2056 // Finally ::
2057 // 'finally' Block
2058
2059 Expect(Token::TRY, CHECK_OK);
2060
Ben Murdoch257744e2011-11-30 15:57:28 +00002061 ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002062 TargetCollector collector(target_list);
2063 Block* try_block;
2064
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002065 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002066 try_block = ParseBlock(NULL, CHECK_OK);
2067 }
2068
2069 Block* catch_block = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002070 Variable* catch_var = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002071 Block* finally_block = NULL;
2072
2073 Token::Value tok = peek();
2074 if (tok != Token::CATCH && tok != Token::FINALLY) {
2075 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2076 *ok = false;
2077 return NULL;
2078 }
2079
2080 // If we can break out from the catch block and there is a finally block,
2081 // then we will need to collect jump targets from the catch block. Since
2082 // we don't know yet if there will be a finally block, we always collect
2083 // the jump targets.
Ben Murdoch257744e2011-11-30 15:57:28 +00002084 ZoneList<Label*>* catch_target_list = new(zone()) ZoneList<Label*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002085 TargetCollector catch_collector(catch_target_list);
2086 bool has_catch = false;
2087 if (tok == Token::CATCH) {
2088 has_catch = true;
2089 Consume(Token::CATCH);
2090
2091 Expect(Token::LPAREN, CHECK_OK);
2092 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002093
Steve Block44f0eee2011-05-26 01:26:41 +01002094 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01002095 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2096 *ok = false;
2097 return NULL;
2098 }
2099
Steve Blocka7e24c12009-10-30 11:49:00 +00002100 Expect(Token::RPAREN, CHECK_OK);
2101
2102 if (peek() == Token::LBRACE) {
2103 // Allocate a temporary for holding the finally state while
2104 // executing the finally block.
Steve Block44f0eee2011-05-26 01:26:41 +01002105 catch_var =
2106 top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002107 Literal* name_literal = new(zone()) Literal(name);
2108 VariableProxy* catch_var_use = new(zone()) VariableProxy(catch_var);
2109 Expression* obj =
2110 new(zone()) CatchExtensionObject(name_literal, catch_var_use);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002111 { Target target(&this->target_stack_, &catch_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002112 catch_block = WithHelper(obj, NULL, true, CHECK_OK);
2113 }
2114 } else {
2115 Expect(Token::LBRACE, CHECK_OK);
2116 }
2117
2118 tok = peek();
2119 }
2120
2121 if (tok == Token::FINALLY || !has_catch) {
2122 Consume(Token::FINALLY);
2123 // Declare a variable for holding the finally state while
2124 // executing the finally block.
2125 finally_block = ParseBlock(NULL, CHECK_OK);
2126 }
2127
2128 // Simplify the AST nodes by converting:
2129 // 'try { } catch { } finally { }'
2130 // to:
2131 // 'try { try { } catch { } } finally { }'
2132
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002133 if (catch_block != NULL && finally_block != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002134 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
Steve Block3ce2e202009-11-05 08:53:23 +00002135 TryCatchStatement* statement =
Ben Murdoch8b112d22011-06-08 16:22:53 +01002136 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block);
Steve Blocka7e24c12009-10-30 11:49:00 +00002137 statement->set_escaping_targets(collector.targets());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002138 try_block = new(zone()) Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002139 try_block->AddStatement(statement);
2140 catch_block = NULL;
2141 }
2142
2143 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002144 if (catch_block != NULL) {
2145 ASSERT(finally_block == NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002146 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
2147 result =
2148 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002149 result->set_escaping_targets(collector.targets());
2150 } else {
2151 ASSERT(finally_block != NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002152 result = new(zone()) TryFinallyStatement(try_block, finally_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002153 // Add the jump targets of the try block and the catch block.
2154 for (int i = 0; i < collector.targets()->length(); i++) {
2155 catch_collector.AddTarget(collector.targets()->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002156 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002157 result->set_escaping_targets(catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002158 }
2159
2160 return result;
2161}
2162
2163
Steve Block3ce2e202009-11-05 08:53:23 +00002164DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2165 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002166 // DoStatement ::
2167 // 'do' Statement 'while' '(' Expression ')' ';'
2168
Ben Murdoch8b112d22011-06-08 16:22:53 +01002169 DoWhileStatement* loop = new(zone()) DoWhileStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002170 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002171
2172 Expect(Token::DO, CHECK_OK);
2173 Statement* body = ParseStatement(NULL, CHECK_OK);
2174 Expect(Token::WHILE, CHECK_OK);
2175 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002176
2177 if (loop != NULL) {
2178 int position = scanner().location().beg_pos;
2179 loop->set_condition_position(position);
2180 }
2181
Steve Blocka7e24c12009-10-30 11:49:00 +00002182 Expression* cond = ParseExpression(true, CHECK_OK);
2183 Expect(Token::RPAREN, CHECK_OK);
2184
2185 // Allow do-statements to be terminated with and without
2186 // semi-colons. This allows code such as 'do;while(0)return' to
2187 // parse, which would not be the case if we had used the
2188 // ExpectSemicolon() functionality here.
2189 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2190
Steve Block3ce2e202009-11-05 08:53:23 +00002191 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002192 return loop;
2193}
2194
2195
Steve Block3ce2e202009-11-05 08:53:23 +00002196WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002197 // WhileStatement ::
2198 // 'while' '(' Expression ')' Statement
2199
Ben Murdoch8b112d22011-06-08 16:22:53 +01002200 WhileStatement* loop = new(zone()) WhileStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002201 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002202
2203 Expect(Token::WHILE, CHECK_OK);
2204 Expect(Token::LPAREN, CHECK_OK);
2205 Expression* cond = ParseExpression(true, CHECK_OK);
2206 Expect(Token::RPAREN, CHECK_OK);
2207 Statement* body = ParseStatement(NULL, CHECK_OK);
2208
Steve Block3ce2e202009-11-05 08:53:23 +00002209 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002210 return loop;
2211}
2212
2213
2214Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2215 // ForStatement ::
2216 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2217
2218 Statement* init = NULL;
2219
2220 Expect(Token::FOR, CHECK_OK);
2221 Expect(Token::LPAREN, CHECK_OK);
2222 if (peek() != Token::SEMICOLON) {
2223 if (peek() == Token::VAR || peek() == Token::CONST) {
2224 Expression* each = NULL;
2225 Block* variable_statement =
2226 ParseVariableDeclarations(false, &each, CHECK_OK);
2227 if (peek() == Token::IN && each != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002228 ForInStatement* loop = new(zone()) ForInStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002229 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002230
2231 Expect(Token::IN, CHECK_OK);
2232 Expression* enumerable = ParseExpression(true, CHECK_OK);
2233 Expect(Token::RPAREN, CHECK_OK);
2234
2235 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002236 loop->Initialize(each, enumerable, body);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002237 Block* result = new(zone()) Block(NULL, 2, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002238 result->AddStatement(variable_statement);
2239 result->AddStatement(loop);
2240 // Parsed for-in loop w/ variable/const declaration.
2241 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002242 } else {
2243 init = variable_statement;
2244 }
2245
2246 } else {
2247 Expression* expression = ParseExpression(false, CHECK_OK);
2248 if (peek() == Token::IN) {
2249 // Signal a reference error if the expression is an invalid
2250 // left-hand side expression. We could report this as a syntax
2251 // error here but for compatibility with JSC we choose to report
2252 // the error at runtime.
2253 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002254 Handle<String> type =
2255 isolate()->factory()->invalid_lhs_in_for_in_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002256 expression = NewThrowReferenceError(type);
2257 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01002258 ForInStatement* loop = new(zone()) ForInStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002259 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002260
2261 Expect(Token::IN, CHECK_OK);
2262 Expression* enumerable = ParseExpression(true, CHECK_OK);
2263 Expect(Token::RPAREN, CHECK_OK);
2264
2265 Statement* body = ParseStatement(NULL, CHECK_OK);
2266 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002267 // Parsed for-in loop.
2268 return loop;
2269
2270 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002271 init = new(zone()) ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002272 }
2273 }
2274 }
2275
2276 // Standard 'for' loop
Ben Murdoch8b112d22011-06-08 16:22:53 +01002277 ForStatement* loop = new(zone()) ForStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002278 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002279
2280 // Parsed initializer at this point.
2281 Expect(Token::SEMICOLON, CHECK_OK);
2282
2283 Expression* cond = NULL;
2284 if (peek() != Token::SEMICOLON) {
2285 cond = ParseExpression(true, CHECK_OK);
2286 }
2287 Expect(Token::SEMICOLON, CHECK_OK);
2288
2289 Statement* next = NULL;
2290 if (peek() != Token::RPAREN) {
2291 Expression* exp = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002292 next = new(zone()) ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002293 }
2294 Expect(Token::RPAREN, CHECK_OK);
2295
2296 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002297 if (loop) loop->Initialize(init, cond, next, body);
2298 return loop;
2299}
2300
2301
2302// Precedence = 1
2303Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2304 // Expression ::
2305 // AssignmentExpression
2306 // Expression ',' AssignmentExpression
2307
2308 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2309 while (peek() == Token::COMMA) {
2310 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002311 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002312 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002313 result = new(zone()) BinaryOperation(Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002314 }
2315 return result;
2316}
2317
2318
2319// Precedence = 2
2320Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2321 // AssignmentExpression ::
2322 // ConditionalExpression
2323 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2324
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002325 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002326 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2327
2328 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002329 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002330 // Parsed conditional expression only (no assignment).
2331 return expression;
2332 }
2333
2334 // Signal a reference error if the expression is an invalid left-hand
2335 // side expression. We could report this as a syntax error here but
2336 // for compatibility with JSC we choose to report the error at
2337 // runtime.
2338 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002339 Handle<String> type =
2340 isolate()->factory()->invalid_lhs_in_assignment_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002341 expression = NewThrowReferenceError(type);
2342 }
2343
Steve Block44f0eee2011-05-26 01:26:41 +01002344 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002345 // Assignment to eval or arguments is disallowed in strict mode.
2346 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2347 }
2348
Steve Blocka7e24c12009-10-30 11:49:00 +00002349 Token::Value op = Next(); // Get assignment operator.
2350 int pos = scanner().location().beg_pos;
2351 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2352
2353 // TODO(1231235): We try to estimate the set of properties set by
2354 // constructors. We define a new property whenever there is an
2355 // assignment to a property of 'this'. We should probably only add
2356 // properties if we haven't seen them before. Otherwise we'll
2357 // probably overestimate the number of properties.
2358 Property* property = expression ? expression->AsProperty() : NULL;
2359 if (op == Token::ASSIGN &&
2360 property != NULL &&
2361 property->obj()->AsVariableProxy() != NULL &&
2362 property->obj()->AsVariableProxy()->is_this()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002363 lexical_scope_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002364 }
2365
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002366 // If we assign a function literal to a property we pretenure the
2367 // literal so it can be added as a constant function property.
2368 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2369 right->AsFunctionLiteral()->set_pretenure(true);
2370 }
2371
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002372 if (fni_ != NULL) {
2373 // Check if the right hand side is a call to avoid inferring a
2374 // name if we're dealing with "a = function(){...}();"-like
2375 // expression.
2376 if ((op == Token::INIT_VAR
2377 || op == Token::INIT_CONST
2378 || op == Token::ASSIGN)
2379 && (right->AsCall() == NULL)) {
2380 fni_->Infer();
2381 }
2382 fni_->Leave();
2383 }
2384
Ben Murdoch8b112d22011-06-08 16:22:53 +01002385 return new(zone()) Assignment(op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002386}
2387
2388
2389// Precedence = 3
2390Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2391 // ConditionalExpression ::
2392 // LogicalOrExpression
2393 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2394
2395 // We start using the binary expression parser for prec >= 4 only!
2396 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2397 if (peek() != Token::CONDITIONAL) return expression;
2398 Consume(Token::CONDITIONAL);
2399 // In parsing the first assignment expression in conditional
2400 // expressions we always accept the 'in' keyword; see ECMA-262,
2401 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002402 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002403 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2404 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002405 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002406 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002407 return new(zone()) Conditional(expression, left, right,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002408 left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002409}
2410
2411
2412static int Precedence(Token::Value tok, bool accept_IN) {
2413 if (tok == Token::IN && !accept_IN)
2414 return 0; // 0 precedence will terminate binary expression parsing
2415
2416 return Token::Precedence(tok);
2417}
2418
2419
2420// Precedence >= 4
2421Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2422 ASSERT(prec >= 4);
2423 Expression* x = ParseUnaryExpression(CHECK_OK);
2424 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2425 // prec1 >= 4
2426 while (Precedence(peek(), accept_IN) == prec1) {
2427 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002428 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002429 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2430
2431 // Compute some expressions involving only number literals.
2432 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2433 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2434 double x_val = x->AsLiteral()->handle()->Number();
2435 double y_val = y->AsLiteral()->handle()->Number();
2436
2437 switch (op) {
2438 case Token::ADD:
2439 x = NewNumberLiteral(x_val + y_val);
2440 continue;
2441 case Token::SUB:
2442 x = NewNumberLiteral(x_val - y_val);
2443 continue;
2444 case Token::MUL:
2445 x = NewNumberLiteral(x_val * y_val);
2446 continue;
2447 case Token::DIV:
2448 x = NewNumberLiteral(x_val / y_val);
2449 continue;
2450 case Token::BIT_OR:
2451 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2452 continue;
2453 case Token::BIT_AND:
2454 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2455 continue;
2456 case Token::BIT_XOR:
2457 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2458 continue;
2459 case Token::SHL: {
2460 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2461 x = NewNumberLiteral(value);
2462 continue;
2463 }
2464 case Token::SHR: {
2465 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2466 uint32_t value = DoubleToUint32(x_val) >> shift;
2467 x = NewNumberLiteral(value);
2468 continue;
2469 }
2470 case Token::SAR: {
2471 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2472 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2473 x = NewNumberLiteral(value);
2474 continue;
2475 }
2476 default:
2477 break;
2478 }
2479 }
2480
Steve Blocka7e24c12009-10-30 11:49:00 +00002481 // For now we distinguish between comparisons and other binary
2482 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002483 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002484 if (Token::IsCompareOp(op)) {
2485 // We have a comparison.
2486 Token::Value cmp = op;
2487 switch (op) {
2488 case Token::NE: cmp = Token::EQ; break;
2489 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2490 default: break;
2491 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002492 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002493 if (cmp != op) {
2494 // The comparison was negated - add a NOT.
Ben Murdoch257744e2011-11-30 15:57:28 +00002495 x = new(zone()) UnaryOperation(Token::NOT, x, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002496 }
2497
2498 } else {
2499 // We have a "normal" binary operation.
Ben Murdoch8b112d22011-06-08 16:22:53 +01002500 x = new(zone()) BinaryOperation(op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002501 }
2502 }
2503 }
2504 return x;
2505}
2506
2507
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002508Expression* Parser::NewCompareNode(Token::Value op,
2509 Expression* x,
2510 Expression* y,
2511 int position) {
2512 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002513 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002514 bool is_strict = (op == Token::EQ_STRICT);
2515 Literal* x_literal = x->AsLiteral();
2516 if (x_literal != NULL && x_literal->IsNull()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002517 return new(zone()) CompareToNull(is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002518 }
2519
2520 Literal* y_literal = y->AsLiteral();
2521 if (y_literal != NULL && y_literal->IsNull()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002522 return new(zone()) CompareToNull(is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002523 }
2524 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01002525 return new(zone()) CompareOperation(op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002526}
2527
2528
Steve Blocka7e24c12009-10-30 11:49:00 +00002529Expression* Parser::ParseUnaryExpression(bool* ok) {
2530 // UnaryExpression ::
2531 // PostfixExpression
2532 // 'delete' UnaryExpression
2533 // 'void' UnaryExpression
2534 // 'typeof' UnaryExpression
2535 // '++' UnaryExpression
2536 // '--' UnaryExpression
2537 // '+' UnaryExpression
2538 // '-' UnaryExpression
2539 // '~' UnaryExpression
2540 // '!' UnaryExpression
2541
2542 Token::Value op = peek();
2543 if (Token::IsUnaryOp(op)) {
2544 op = Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00002545 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002546 Expression* expression = ParseUnaryExpression(CHECK_OK);
2547
2548 // Compute some expressions involving only number literals.
2549 if (expression != NULL && expression->AsLiteral() &&
2550 expression->AsLiteral()->handle()->IsNumber()) {
2551 double value = expression->AsLiteral()->handle()->Number();
2552 switch (op) {
2553 case Token::ADD:
2554 return expression;
2555 case Token::SUB:
2556 return NewNumberLiteral(-value);
2557 case Token::BIT_NOT:
2558 return NewNumberLiteral(~DoubleToInt32(value));
2559 default: break;
2560 }
2561 }
2562
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002563 // "delete identifier" is a syntax error in strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01002564 if (op == Token::DELETE && top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002565 VariableProxy* operand = expression->AsVariableProxy();
2566 if (operand != NULL && !operand->is_this()) {
2567 ReportMessage("strict_delete", Vector<const char*>::empty());
2568 *ok = false;
2569 return NULL;
2570 }
2571 }
2572
Ben Murdoch257744e2011-11-30 15:57:28 +00002573 return new(zone()) UnaryOperation(op, expression, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002574
2575 } else if (Token::IsCountOp(op)) {
2576 op = Next();
2577 Expression* expression = ParseUnaryExpression(CHECK_OK);
2578 // Signal a reference error if the expression is an invalid
2579 // left-hand side expression. We could report this as a syntax
2580 // error here but for compatibility with JSC we choose to report the
2581 // error at runtime.
2582 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002583 Handle<String> type =
2584 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002585 expression = NewThrowReferenceError(type);
2586 }
Steve Block1e0659c2011-05-24 12:43:12 +01002587
Steve Block44f0eee2011-05-26 01:26:41 +01002588 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002589 // Prefix expression operand in strict mode may not be eval or arguments.
2590 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2591 }
2592
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002593 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002594 return new(zone()) CountOperation(op,
2595 true /* prefix */,
2596 expression,
2597 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002598
2599 } else {
2600 return ParsePostfixExpression(ok);
2601 }
2602}
2603
2604
2605Expression* Parser::ParsePostfixExpression(bool* ok) {
2606 // PostfixExpression ::
2607 // LeftHandSideExpression ('++' | '--')?
2608
2609 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002610 if (!scanner().has_line_terminator_before_next() &&
2611 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002612 // Signal a reference error if the expression is an invalid
2613 // left-hand side expression. We could report this as a syntax
2614 // error here but for compatibility with JSC we choose to report the
2615 // error at runtime.
2616 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002617 Handle<String> type =
2618 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002619 expression = NewThrowReferenceError(type);
2620 }
Steve Block1e0659c2011-05-24 12:43:12 +01002621
Steve Block44f0eee2011-05-26 01:26:41 +01002622 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002623 // Postfix expression operand in strict mode may not be eval or arguments.
2624 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2625 }
2626
Steve Blocka7e24c12009-10-30 11:49:00 +00002627 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002628 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002629 expression =
2630 new(zone()) CountOperation(next,
2631 false /* postfix */,
2632 expression,
2633 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002634 }
2635 return expression;
2636}
2637
2638
2639Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2640 // LeftHandSideExpression ::
2641 // (NewExpression | MemberExpression) ...
2642
2643 Expression* result;
2644 if (peek() == Token::NEW) {
2645 result = ParseNewExpression(CHECK_OK);
2646 } else {
2647 result = ParseMemberExpression(CHECK_OK);
2648 }
2649
2650 while (true) {
2651 switch (peek()) {
2652 case Token::LBRACK: {
2653 Consume(Token::LBRACK);
2654 int pos = scanner().location().beg_pos;
2655 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002656 result = new(zone()) Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002657 Expect(Token::RBRACK, CHECK_OK);
2658 break;
2659 }
2660
2661 case Token::LPAREN: {
2662 int pos = scanner().location().beg_pos;
2663 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2664
2665 // Keep track of eval() calls since they disable all local variable
2666 // optimizations.
2667 // The calls that need special treatment are the
2668 // direct (i.e. not aliased) eval calls. These calls are all of the
2669 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002670 // declared in the current scope chain.
2671 // These calls are marked as potentially direct eval calls. Whether
2672 // they are actually direct calls to eval is determined at run time.
2673 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2674 // in the local scope chain. It only matters that it's called "eval",
2675 // is called without a receiver and it refers to the original eval
2676 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002677 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01002678 if (callee != NULL &&
2679 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002680 Handle<String> name = callee->name();
2681 Variable* var = top_scope_->Lookup(name);
2682 if (var == NULL) {
2683 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002684 }
2685 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002686 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002687 break;
2688 }
2689
2690 case Token::PERIOD: {
2691 Consume(Token::PERIOD);
2692 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002693 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002694 result = new(zone()) Property(result, new(zone()) Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002695 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002696 break;
2697 }
2698
2699 default:
2700 return result;
2701 }
2702 }
2703}
2704
2705
Steve Blocka7e24c12009-10-30 11:49:00 +00002706Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2707 // NewExpression ::
2708 // ('new')+ MemberExpression
2709
2710 // The grammar for new expressions is pretty warped. The keyword
2711 // 'new' can either be a part of the new expression (where it isn't
2712 // followed by an argument list) or a part of the member expression,
2713 // where it must be followed by an argument list. To accommodate
2714 // this, we parse the 'new' keywords greedily and keep track of how
2715 // many we have parsed. This information is then passed on to the
2716 // member expression parser, which is only allowed to match argument
2717 // lists as long as it has 'new' prefixes left
2718 Expect(Token::NEW, CHECK_OK);
2719 PositionStack::Element pos(stack, scanner().location().beg_pos);
2720
2721 Expression* result;
2722 if (peek() == Token::NEW) {
2723 result = ParseNewPrefix(stack, CHECK_OK);
2724 } else {
2725 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2726 }
2727
2728 if (!stack->is_empty()) {
2729 int last = stack->pop();
Ben Murdoch257744e2011-11-30 15:57:28 +00002730 result = new(zone()) CallNew(result,
2731 new(zone()) ZoneList<Expression*>(0),
2732 last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002733 }
2734 return result;
2735}
2736
2737
2738Expression* Parser::ParseNewExpression(bool* ok) {
2739 PositionStack stack(ok);
2740 return ParseNewPrefix(&stack, ok);
2741}
2742
2743
2744Expression* Parser::ParseMemberExpression(bool* ok) {
2745 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2746}
2747
2748
2749Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2750 bool* ok) {
2751 // MemberExpression ::
2752 // (PrimaryExpression | FunctionLiteral)
2753 // ('[' Expression ']' | '.' Identifier | Arguments)*
2754
2755 // Parse the initial primary or function expression.
2756 Expression* result = NULL;
2757 if (peek() == Token::FUNCTION) {
2758 Expect(Token::FUNCTION, CHECK_OK);
2759 int function_token_position = scanner().location().beg_pos;
2760 Handle<String> name;
Steve Block1e0659c2011-05-24 12:43:12 +01002761 bool is_reserved_name = false;
2762 if (peek_any_identifier()) {
2763 name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK);
2764 }
2765 result = ParseFunctionLiteral(name, is_reserved_name,
2766 function_token_position, NESTED, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002767 } else {
2768 result = ParsePrimaryExpression(CHECK_OK);
2769 }
2770
2771 while (true) {
2772 switch (peek()) {
2773 case Token::LBRACK: {
2774 Consume(Token::LBRACK);
2775 int pos = scanner().location().beg_pos;
2776 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002777 result = new(zone()) Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002778 Expect(Token::RBRACK, CHECK_OK);
2779 break;
2780 }
2781 case Token::PERIOD: {
2782 Consume(Token::PERIOD);
2783 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002784 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002785 result = new(zone()) Property(result, new(zone()) Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002786 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002787 break;
2788 }
2789 case Token::LPAREN: {
2790 if ((stack == NULL) || stack->is_empty()) return result;
2791 // Consume one of the new prefixes (already parsed).
2792 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2793 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002794 result = new CallNew(result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002795 break;
2796 }
2797 default:
2798 return result;
2799 }
2800 }
2801}
2802
2803
2804DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2805 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2806 // contexts this is used as a statement which invokes the debugger as i a
2807 // break point is present.
2808 // DebuggerStatement ::
2809 // 'debugger' ';'
2810
2811 Expect(Token::DEBUGGER, CHECK_OK);
2812 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002813 return new(zone()) DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002814}
2815
2816
2817void Parser::ReportUnexpectedToken(Token::Value token) {
2818 // We don't report stack overflows here, to avoid increasing the
2819 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002820 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002821 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002822 // Four of the tokens are treated specially
2823 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002824 case Token::EOS:
2825 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2826 case Token::NUMBER:
2827 return ReportMessage("unexpected_token_number",
2828 Vector<const char*>::empty());
2829 case Token::STRING:
2830 return ReportMessage("unexpected_token_string",
2831 Vector<const char*>::empty());
2832 case Token::IDENTIFIER:
2833 return ReportMessage("unexpected_token_identifier",
2834 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002835 case Token::FUTURE_RESERVED_WORD:
Steve Block44f0eee2011-05-26 01:26:41 +01002836 return ReportMessage(top_scope_->is_strict_mode() ?
Steve Block1e0659c2011-05-24 12:43:12 +01002837 "unexpected_strict_reserved" :
2838 "unexpected_token_identifier",
2839 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002840 default:
2841 const char* name = Token::String(token);
2842 ASSERT(name != NULL);
2843 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002844 }
2845}
2846
2847
Leon Clarkeac952652010-07-15 11:15:24 +01002848void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2849 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2850 const char* element[1] = { *name_string };
2851 ReportMessage("invalid_preparser_data",
2852 Vector<const char*>(element, 1));
2853 *ok = false;
2854}
2855
2856
Steve Blocka7e24c12009-10-30 11:49:00 +00002857Expression* Parser::ParsePrimaryExpression(bool* ok) {
2858 // PrimaryExpression ::
2859 // 'this'
2860 // 'null'
2861 // 'true'
2862 // 'false'
2863 // Identifier
2864 // Number
2865 // String
2866 // ArrayLiteral
2867 // ObjectLiteral
2868 // RegExpLiteral
2869 // '(' Expression ')'
2870
2871 Expression* result = NULL;
2872 switch (peek()) {
2873 case Token::THIS: {
2874 Consume(Token::THIS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002875 VariableProxy* recv = top_scope_->receiver();
2876 result = recv;
Steve Blocka7e24c12009-10-30 11:49:00 +00002877 break;
2878 }
2879
2880 case Token::NULL_LITERAL:
2881 Consume(Token::NULL_LITERAL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002882 result = new(zone()) Literal(isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002883 break;
2884
2885 case Token::TRUE_LITERAL:
2886 Consume(Token::TRUE_LITERAL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002887 result = new(zone()) Literal(isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002888 break;
2889
2890 case Token::FALSE_LITERAL:
2891 Consume(Token::FALSE_LITERAL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002892 result = new(zone()) Literal(isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002893 break;
2894
Steve Block1e0659c2011-05-24 12:43:12 +01002895 case Token::IDENTIFIER:
2896 case Token::FUTURE_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00002897 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002898 if (fni_ != NULL) fni_->PushVariableName(name);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002899 result = top_scope_->NewUnresolved(name,
2900 inside_with(),
2901 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002902 break;
2903 }
2904
2905 case Token::NUMBER: {
2906 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01002907 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002908 double value = StringToDouble(isolate()->unicode_cache(),
2909 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01002910 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002911 result = NewNumberLiteral(value);
2912 break;
2913 }
2914
2915 case Token::STRING: {
2916 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01002917 Handle<String> symbol = GetSymbol(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002918 result = new(zone()) Literal(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002919 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002920 break;
2921 }
2922
2923 case Token::ASSIGN_DIV:
2924 result = ParseRegExpLiteral(true, CHECK_OK);
2925 break;
2926
2927 case Token::DIV:
2928 result = ParseRegExpLiteral(false, CHECK_OK);
2929 break;
2930
2931 case Token::LBRACK:
2932 result = ParseArrayLiteral(CHECK_OK);
2933 break;
2934
2935 case Token::LBRACE:
2936 result = ParseObjectLiteral(CHECK_OK);
2937 break;
2938
2939 case Token::LPAREN:
2940 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002941 // Heuristically try to detect immediately called functions before
2942 // seeing the call parentheses.
2943 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00002944 result = ParseExpression(true, CHECK_OK);
2945 Expect(Token::RPAREN, CHECK_OK);
2946 break;
2947
2948 case Token::MOD:
2949 if (allow_natives_syntax_ || extension_ != NULL) {
2950 result = ParseV8Intrinsic(CHECK_OK);
2951 break;
2952 }
2953 // If we're not allowing special syntax we fall-through to the
2954 // default case.
2955
2956 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01002957 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00002958 ReportUnexpectedToken(tok);
2959 *ok = false;
2960 return NULL;
2961 }
2962 }
2963
2964 return result;
2965}
2966
2967
Leon Clarke4515c472010-02-03 11:58:03 +00002968void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
2969 Handle<FixedArray> literals,
2970 bool* is_simple,
2971 int* depth) {
2972 // Fill in the literals.
2973 // Accumulate output values in local variables.
2974 bool is_simple_acc = true;
2975 int depth_acc = 1;
2976 for (int i = 0; i < values->length(); i++) {
2977 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
2978 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2979 depth_acc = m_literal->depth() + 1;
2980 }
2981 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
2982 if (boilerplate_value->IsUndefined()) {
2983 literals->set_the_hole(i);
2984 is_simple_acc = false;
2985 } else {
2986 literals->set(i, *boilerplate_value);
2987 }
2988 }
2989
2990 *is_simple = is_simple_acc;
2991 *depth = depth_acc;
2992}
2993
2994
Steve Blocka7e24c12009-10-30 11:49:00 +00002995Expression* Parser::ParseArrayLiteral(bool* ok) {
2996 // ArrayLiteral ::
2997 // '[' Expression? (',' Expression?)* ']'
2998
Ben Murdoch257744e2011-11-30 15:57:28 +00002999 ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003000 Expect(Token::LBRACK, CHECK_OK);
3001 while (peek() != Token::RBRACK) {
3002 Expression* elem;
3003 if (peek() == Token::COMMA) {
3004 elem = GetLiteralTheHole();
3005 } else {
3006 elem = ParseAssignmentExpression(true, CHECK_OK);
3007 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003008 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00003009 if (peek() != Token::RBRACK) {
3010 Expect(Token::COMMA, CHECK_OK);
3011 }
3012 }
3013 Expect(Token::RBRACK, CHECK_OK);
3014
3015 // Update the scope information before the pre-parsing bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003016 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003017
Steve Blocka7e24c12009-10-30 11:49:00 +00003018 // Allocate a fixed array with all the literals.
3019 Handle<FixedArray> literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003020 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003021
3022 // Fill in the literals.
3023 bool is_simple = true;
3024 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003025 for (int i = 0, n = values->length(); i < n; i++) {
3026 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003027 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3028 depth = m_literal->depth() + 1;
3029 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003030 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003031 if (boilerplate_value->IsUndefined()) {
3032 literals->set_the_hole(i);
3033 is_simple = false;
3034 } else {
3035 literals->set(i, *boilerplate_value);
3036 }
3037 }
3038
Iain Merrick75681382010-08-19 15:07:18 +01003039 // Simple and shallow arrays can be lazily copied, we transform the
3040 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003041 if (is_simple && depth == 1 && values->length() > 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01003042 literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003043 }
3044
Ben Murdoch8b112d22011-06-08 16:22:53 +01003045 return new(zone()) ArrayLiteral(literals, values,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003046 literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003047}
3048
3049
3050bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3051 return property != NULL &&
3052 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3053}
3054
3055
3056bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003057 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003058 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3059 return lit != NULL && lit->is_simple();
3060}
3061
Iain Merrick75681382010-08-19 15:07:18 +01003062
3063bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3064 Expression* value) {
3065 // If value is a literal the property value is already set in the
3066 // boilerplate object.
3067 if (value->AsLiteral() != NULL) return false;
3068 // If value is a materialized literal the property value is already set
3069 // in the boilerplate object if it is simple.
3070 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3071 return true;
3072}
3073
3074
Steve Blocka7e24c12009-10-30 11:49:00 +00003075Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3076 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003077 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003078 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3079 if (object_literal != NULL) {
3080 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003081 if (object_literal->fast_elements()) {
3082 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3083 } else {
3084 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3085 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003086 result->set(kElementsSlot, *object_literal->constant_properties());
3087 } else {
3088 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3089 ASSERT(array_literal != NULL && array_literal->is_simple());
3090 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003091 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003092 }
3093 return result;
3094}
3095
3096
3097CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3098 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3099 return static_cast<Type>(type_value->value());
3100}
3101
3102
3103Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3104 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3105}
3106
3107
3108Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3109 if (expression->AsLiteral() != NULL) {
3110 return expression->AsLiteral()->handle();
3111 }
3112 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3113 return CompileTimeValue::GetValue(expression);
3114 }
Steve Block44f0eee2011-05-26 01:26:41 +01003115 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003116}
3117
Steve Block1e0659c2011-05-24 12:43:12 +01003118// Defined in ast.cc
3119bool IsEqualString(void* first, void* second);
3120bool IsEqualNumber(void* first, void* second);
3121
3122
3123// Validation per 11.1.5 Object Initialiser
3124class ObjectLiteralPropertyChecker {
3125 public:
3126 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3127 props(&IsEqualString),
3128 elems(&IsEqualNumber),
3129 parser_(parser),
3130 strict_(strict) {
3131 }
3132
3133 void CheckProperty(
3134 ObjectLiteral::Property* property,
3135 Scanner::Location loc,
3136 bool* ok);
3137
3138 private:
3139 enum PropertyKind {
3140 kGetAccessor = 0x01,
3141 kSetAccessor = 0x02,
3142 kAccessor = kGetAccessor | kSetAccessor,
3143 kData = 0x04
3144 };
3145
3146 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3147 switch (property->kind()) {
3148 case ObjectLiteral::Property::GETTER:
3149 return kGetAccessor;
3150 case ObjectLiteral::Property::SETTER:
3151 return kSetAccessor;
3152 default:
3153 return kData;
3154 }
3155 }
3156
3157 HashMap props;
3158 HashMap elems;
3159 Parser* parser_;
3160 bool strict_;
3161};
3162
3163
3164void ObjectLiteralPropertyChecker::CheckProperty(
3165 ObjectLiteral::Property* property,
3166 Scanner::Location loc,
3167 bool* ok) {
3168
3169 ASSERT(property != NULL);
3170
3171 Literal *lit = property->key();
3172 Handle<Object> handle = lit->handle();
3173
3174 uint32_t hash;
3175 HashMap* map;
3176 void* key;
3177
3178 if (handle->IsSymbol()) {
3179 Handle<String> name(String::cast(*handle));
3180 if (name->AsArrayIndex(&hash)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003181 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
Steve Block1e0659c2011-05-24 12:43:12 +01003182 key = key_handle.location();
3183 map = &elems;
3184 } else {
3185 key = handle.location();
3186 hash = name->Hash();
3187 map = &props;
3188 }
3189 } else if (handle->ToArrayIndex(&hash)) {
3190 key = handle.location();
3191 map = &elems;
3192 } else {
3193 ASSERT(handle->IsNumber());
3194 double num = handle->Number();
3195 char arr[100];
3196 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3197 const char* str = DoubleToCString(num, buffer);
Steve Block44f0eee2011-05-26 01:26:41 +01003198 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
Steve Block1e0659c2011-05-24 12:43:12 +01003199 key = name.location();
3200 hash = name->Hash();
3201 map = &props;
3202 }
3203
3204 // Lookup property previously defined, if any.
3205 HashMap::Entry* entry = map->Lookup(key, hash, true);
3206 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3207 intptr_t curr = GetPropertyKind(property);
3208
3209 // Duplicate data properties are illegal in strict mode.
3210 if (strict_ && (curr & prev & kData) != 0) {
3211 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3212 Vector<const char*>::empty());
3213 *ok = false;
3214 return;
3215 }
3216 // Data property conflicting with an accessor.
3217 if (((curr & kData) && (prev & kAccessor)) ||
3218 ((prev & kData) && (curr & kAccessor))) {
3219 parser_->ReportMessageAt(loc, "accessor_data_property",
3220 Vector<const char*>::empty());
3221 *ok = false;
3222 return;
3223 }
3224 // Two accessors of the same type conflicting
3225 if ((curr & prev & kAccessor) != 0) {
3226 parser_->ReportMessageAt(loc, "accessor_get_set",
3227 Vector<const char*>::empty());
3228 *ok = false;
3229 return;
3230 }
3231
3232 // Update map
3233 entry->value = reinterpret_cast<void*> (prev | curr);
3234 *ok = true;
3235}
3236
Steve Blocka7e24c12009-10-30 11:49:00 +00003237
Leon Clarke4515c472010-02-03 11:58:03 +00003238void Parser::BuildObjectLiteralConstantProperties(
3239 ZoneList<ObjectLiteral::Property*>* properties,
3240 Handle<FixedArray> constant_properties,
3241 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003242 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003243 int* depth) {
3244 int position = 0;
3245 // Accumulate the value in local variables and store it at the end.
3246 bool is_simple_acc = true;
3247 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003248 uint32_t max_element_index = 0;
3249 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003250 for (int i = 0; i < properties->length(); i++) {
3251 ObjectLiteral::Property* property = properties->at(i);
3252 if (!IsBoilerplateProperty(property)) {
3253 is_simple_acc = false;
3254 continue;
3255 }
3256 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3257 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3258 depth_acc = m_literal->depth() + 1;
3259 }
3260
3261 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3262 // value for COMPUTED properties, the real value is filled in at
3263 // runtime. The enumeration order is maintained.
3264 Handle<Object> key = property->key()->handle();
3265 Handle<Object> value = GetBoilerplateValue(property->value());
3266 is_simple_acc = is_simple_acc && !value->IsUndefined();
3267
Steve Block6ded16b2010-05-10 14:33:55 +01003268 // Keep track of the number of elements in the object literal and
3269 // the largest element index. If the largest element index is
3270 // much larger than the number of elements, creating an object
3271 // literal with fast elements will be a waste of space.
3272 uint32_t element_index = 0;
3273 if (key->IsString()
3274 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3275 && element_index > max_element_index) {
3276 max_element_index = element_index;
3277 elements++;
3278 } else if (key->IsSmi()) {
3279 int key_value = Smi::cast(*key)->value();
3280 if (key_value > 0
3281 && static_cast<uint32_t>(key_value) > max_element_index) {
3282 max_element_index = key_value;
3283 }
3284 elements++;
3285 }
3286
Leon Clarke4515c472010-02-03 11:58:03 +00003287 // Add name, value pair to the fixed array.
3288 constant_properties->set(position++, *key);
3289 constant_properties->set(position++, *value);
3290 }
Steve Block6ded16b2010-05-10 14:33:55 +01003291 *fast_elements =
3292 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003293 *is_simple = is_simple_acc;
3294 *depth = depth_acc;
3295}
3296
3297
Ben Murdochbb769b22010-08-11 14:56:33 +01003298ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3299 bool* ok) {
3300 // Special handling of getter and setter syntax:
3301 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3302 // We have already read the "get" or "set" keyword.
3303 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003304 bool is_keyword = Token::IsKeyword(next);
3305 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003306 next == Token::FUTURE_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003307 next == Token::STRING || is_keyword) {
3308 Handle<String> name;
3309 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003310 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003311 } else {
3312 name = GetSymbol(CHECK_OK);
3313 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003314 FunctionLiteral* value =
3315 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003316 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003317 RelocInfo::kNoPosition,
3318 DECLARATION,
3319 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003320 // Allow any number of parameters for compatiabilty with JSC.
3321 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003322 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003323 new(zone()) ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003324 return property;
3325 } else {
3326 ReportUnexpectedToken(next);
3327 *ok = false;
3328 return NULL;
3329 }
3330}
3331
3332
Steve Blocka7e24c12009-10-30 11:49:00 +00003333Expression* Parser::ParseObjectLiteral(bool* ok) {
3334 // ObjectLiteral ::
3335 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003336 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3337 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003338 // )*[','] '}'
3339
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003340 ZoneList<ObjectLiteral::Property*>* properties =
Ben Murdoch257744e2011-11-30 15:57:28 +00003341 new(zone()) ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003342 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003343 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003344
Steve Block44f0eee2011-05-26 01:26:41 +01003345 ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003346
Steve Blocka7e24c12009-10-30 11:49:00 +00003347 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003348 Scanner::Location loc = scanner().location();
3349
Steve Blocka7e24c12009-10-30 11:49:00 +00003350 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003351 if (fni_ != NULL) fni_->Enter();
3352
Steve Blocka7e24c12009-10-30 11:49:00 +00003353 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003354 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003355
3356 // Location of the property name token
3357 Scanner::Location loc = scanner().peek_location();
3358
Ben Murdochbb769b22010-08-11 14:56:33 +01003359 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003360 case Token::FUTURE_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003361 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003362 bool is_getter = false;
3363 bool is_setter = false;
3364 Handle<String> id =
3365 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003366 if (fni_ != NULL) fni_->PushLiteralName(id);
3367
Ben Murdochbb769b22010-08-11 14:56:33 +01003368 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003369 // Update loc to point to the identifier
3370 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003371 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003372 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3373 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003374 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003375 }
Steve Block1e0659c2011-05-24 12:43:12 +01003376 // Validate the property.
3377 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003378 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003379 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003380
3381 if (fni_ != NULL) {
3382 fni_->Infer();
3383 fni_->Leave();
3384 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003385 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003386 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003387 // Failed to parse as get/set property, so it's just a property
3388 // called "get" or "set".
Ben Murdoch8b112d22011-06-08 16:22:53 +01003389 key = new(zone()) Literal(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003390 break;
3391 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003392 case Token::STRING: {
3393 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003394 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003395 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003396 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003397 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003398 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003399 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003400 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01003401 key = new(zone()) Literal(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003402 break;
3403 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003404 case Token::NUMBER: {
3405 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003406 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003407 double value = StringToDouble(isolate()->unicode_cache(),
3408 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003409 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003410 key = NewNumberLiteral(value);
3411 break;
3412 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003413 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003414 if (Token::IsKeyword(next)) {
3415 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003416 Handle<String> string = GetSymbol(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003417 key = new(zone()) Literal(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003418 } else {
3419 // Unexpected token.
3420 Token::Value next = Next();
3421 ReportUnexpectedToken(next);
3422 *ok = false;
3423 return NULL;
3424 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003425 }
3426
3427 Expect(Token::COLON, CHECK_OK);
3428 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3429
3430 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003431 new(zone()) ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003432
Steve Block44f0eee2011-05-26 01:26:41 +01003433 // Mark object literals that contain function literals and pretenure the
3434 // literal so it can be added as a constant function property.
3435 if (value->AsFunctionLiteral() != NULL) {
3436 has_function = true;
3437 value->AsFunctionLiteral()->set_pretenure(true);
3438 }
3439
Steve Blocka7e24c12009-10-30 11:49:00 +00003440 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3441 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003442 // Validate the property
3443 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003444 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003445
3446 // TODO(1240767): Consider allowing trailing comma.
3447 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003448
3449 if (fni_ != NULL) {
3450 fni_->Infer();
3451 fni_->Leave();
3452 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003453 }
3454 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003455
Steve Blocka7e24c12009-10-30 11:49:00 +00003456 // Computation of literal_index must happen before pre parse bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003457 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003458
Steve Block44f0eee2011-05-26 01:26:41 +01003459 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3460 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003461
Steve Blocka7e24c12009-10-30 11:49:00 +00003462 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003463 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003464 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003465 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003466 constant_properties,
3467 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003468 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003469 &depth);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003470 return new(zone()) ObjectLiteral(constant_properties,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003471 properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003472 literal_index,
3473 is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003474 fast_elements,
Steve Block44f0eee2011-05-26 01:26:41 +01003475 depth,
3476 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003477}
3478
3479
3480Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003481 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003482 Next();
3483 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3484 *ok = false;
3485 return NULL;
3486 }
3487
Steve Block44f0eee2011-05-26 01:26:41 +01003488 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003489
Steve Block9fac8402011-05-12 15:51:54 +01003490 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003491 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003492 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003493 Next();
3494
Ben Murdoch8b112d22011-06-08 16:22:53 +01003495 return new(zone()) RegExpLiteral(js_pattern, js_flags, literal_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003496}
3497
3498
3499ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3500 // Arguments ::
3501 // '(' (AssignmentExpression)*[','] ')'
3502
Ben Murdoch257744e2011-11-30 15:57:28 +00003503 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003504 Expect(Token::LPAREN, CHECK_OK);
3505 bool done = (peek() == Token::RPAREN);
3506 while (!done) {
3507 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003508 result->Add(argument);
Steve Block053d10c2011-06-13 19:13:29 +01003509 if (result->length() > kMaxNumFunctionParameters) {
3510 ReportMessageAt(scanner().location(), "too_many_arguments",
3511 Vector<const char*>::empty());
3512 *ok = false;
3513 return NULL;
3514 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003515 done = (peek() == Token::RPAREN);
3516 if (!done) Expect(Token::COMMA, CHECK_OK);
3517 }
3518 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003519 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003520}
3521
3522
3523FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
Steve Block1e0659c2011-05-24 12:43:12 +01003524 bool name_is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003525 int function_token_position,
3526 FunctionLiteralType type,
3527 bool* ok) {
3528 // Function ::
3529 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003530 bool is_named = !var_name.is_null();
3531
3532 // The name associated with this function. If it's a function expression,
3533 // this is the actual function name, otherwise this is the name of the
3534 // variable declared and initialized with the function (expression). In
3535 // that case, we don't have a function name (it's empty).
Steve Block44f0eee2011-05-26 01:26:41 +01003536 Handle<String> name =
3537 is_named ? var_name : isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003538 // The function name, if any.
Steve Block44f0eee2011-05-26 01:26:41 +01003539 Handle<String> function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003540 if (is_named && (type == EXPRESSION || type == NESTED)) {
3541 function_name = name;
3542 }
3543
3544 int num_parameters = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +01003545 Scope* scope = NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
Ben Murdoch257744e2011-11-30 15:57:28 +00003546 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003547 int materialized_literal_count;
3548 int expected_property_count;
3549 int start_pos;
3550 int end_pos;
3551 bool only_simple_this_property_assignments;
3552 Handle<FixedArray> this_property_assignments;
Steve Blocka7e24c12009-10-30 11:49:00 +00003553 // Parse function body.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003554 { LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003555 top_scope_->SetScopeName(name);
3556
3557 // FormalParameterList ::
3558 // '(' (Identifier)*[','] ')'
3559 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003560 start_pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00003561 Scanner::Location name_loc = Scanner::Location::invalid();
3562 Scanner::Location dupe_loc = Scanner::Location::invalid();
3563 Scanner::Location reserved_loc = Scanner::Location::invalid();
Steve Block1e0659c2011-05-24 12:43:12 +01003564
Steve Blocka7e24c12009-10-30 11:49:00 +00003565 bool done = (peek() == Token::RPAREN);
3566 while (!done) {
Steve Block1e0659c2011-05-24 12:43:12 +01003567 bool is_reserved = false;
3568 Handle<String> param_name =
3569 ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
3570
3571 // Store locations for possible future error reports.
3572 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3573 name_loc = scanner().location();
3574 }
3575 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
3576 dupe_loc = scanner().location();
3577 }
3578 if (!reserved_loc.IsValid() && is_reserved) {
3579 reserved_loc = scanner().location();
3580 }
3581
Steve Block053d10c2011-06-13 19:13:29 +01003582 Variable* parameter = top_scope_->DeclareLocal(param_name,
3583 Variable::VAR,
3584 Scope::PARAMETER);
Steve Block1e0659c2011-05-24 12:43:12 +01003585 top_scope_->AddParameter(parameter);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003586 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003587 if (num_parameters > kMaxNumFunctionParameters) {
3588 ReportMessageAt(scanner().location(), "too_many_parameters",
3589 Vector<const char*>::empty());
3590 *ok = false;
3591 return NULL;
3592 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003593 done = (peek() == Token::RPAREN);
3594 if (!done) Expect(Token::COMMA, CHECK_OK);
3595 }
3596 Expect(Token::RPAREN, CHECK_OK);
3597
3598 Expect(Token::LBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003599
3600 // If we have a named function expression, we add a local variable
3601 // declaration to the body of the function with the name of the
3602 // function and let it refer to the function itself (closure).
3603 // NOTE: We create a proxy and resolve it here so that in the
3604 // future we can change the AST to only refer to VariableProxies
3605 // instead of Variables and Proxis as is the case now.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003606 if (!function_name.is_null() && function_name->length() > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003607 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3608 VariableProxy* fproxy =
3609 top_scope_->NewUnresolved(function_name, inside_with());
3610 fproxy->BindTo(fvar);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003611 body->Add(new(zone()) ExpressionStatement(
3612 new(zone()) Assignment(Token::INIT_CONST, fproxy,
3613 new(zone()) ThisFunction(),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003614 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003615 }
3616
3617 // Determine if the function will be lazily compiled. The mode can
3618 // only be PARSE_LAZILY if the --lazy flag is true.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003619 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3620 top_scope_->outer_scope()->is_global_scope() &&
3621 top_scope_->HasTrivialOuterContext() &&
3622 !parenthesized_function_);
3623 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003624
Ben Murdochb0fe1622011-05-05 13:52:32 +01003625 int function_block_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003626 if (is_lazily_compiled && pre_data() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003627 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003628 if (!entry.is_valid()) {
3629 ReportInvalidPreparseData(name, CHECK_OK);
3630 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003631 end_pos = entry.end_pos();
3632 if (end_pos <= function_block_pos) {
Leon Clarkeac952652010-07-15 11:15:24 +01003633 // End position greater than end of stream is safe, and hard to check.
3634 ReportInvalidPreparseData(name, CHECK_OK);
3635 }
Steve Block44f0eee2011-05-26 01:26:41 +01003636 isolate()->counters()->total_preparse_skipped()->Increment(
3637 end_pos - function_block_pos);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003638 // Seek to position just before terminal '}'.
3639 scanner().SeekForward(end_pos - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003640 materialized_literal_count = entry.literal_count();
3641 expected_property_count = entry.property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003642 only_simple_this_property_assignments = false;
Steve Block44f0eee2011-05-26 01:26:41 +01003643 this_property_assignments = isolate()->factory()->empty_fixed_array();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003644 Expect(Token::RBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003645 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003646 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3647
Steve Block44f0eee2011-05-26 01:26:41 +01003648 materialized_literal_count = lexical_scope.materialized_literal_count();
3649 expected_property_count = lexical_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003650 only_simple_this_property_assignments =
Steve Block44f0eee2011-05-26 01:26:41 +01003651 lexical_scope.only_simple_this_property_assignments();
3652 this_property_assignments = lexical_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003653
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003654 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003655 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003656 }
3657
Steve Block1e0659c2011-05-24 12:43:12 +01003658 // Validate strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01003659 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003660 if (IsEvalOrArguments(name)) {
3661 int position = function_token_position != RelocInfo::kNoPosition
3662 ? function_token_position
3663 : (start_pos > 0 ? start_pos - 1 : start_pos);
3664 Scanner::Location location = Scanner::Location(position, start_pos);
3665 ReportMessageAt(location,
3666 "strict_function_name", Vector<const char*>::empty());
3667 *ok = false;
3668 return NULL;
3669 }
3670 if (name_loc.IsValid()) {
3671 ReportMessageAt(name_loc, "strict_param_name",
3672 Vector<const char*>::empty());
3673 *ok = false;
3674 return NULL;
3675 }
3676 if (dupe_loc.IsValid()) {
3677 ReportMessageAt(dupe_loc, "strict_param_dupe",
3678 Vector<const char*>::empty());
3679 *ok = false;
3680 return NULL;
3681 }
3682 if (name_is_reserved) {
3683 int position = function_token_position != RelocInfo::kNoPosition
3684 ? function_token_position
3685 : (start_pos > 0 ? start_pos - 1 : start_pos);
3686 Scanner::Location location = Scanner::Location(position, start_pos);
3687 ReportMessageAt(location, "strict_reserved_word",
3688 Vector<const char*>::empty());
3689 *ok = false;
3690 return NULL;
3691 }
3692 if (reserved_loc.IsValid()) {
3693 ReportMessageAt(reserved_loc, "strict_reserved_word",
3694 Vector<const char*>::empty());
3695 *ok = false;
3696 return NULL;
3697 }
3698 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3699 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003700 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01003701
3702 FunctionLiteral* function_literal =
3703 new(zone()) FunctionLiteral(name,
3704 scope,
3705 body,
3706 materialized_literal_count,
3707 expected_property_count,
3708 only_simple_this_property_assignments,
3709 this_property_assignments,
3710 num_parameters,
3711 start_pos,
3712 end_pos,
3713 (function_name->length() > 0));
3714 function_literal->set_function_token_position(function_token_position);
3715
3716 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
3717 return function_literal;
Steve Blocka7e24c12009-10-30 11:49:00 +00003718}
3719
3720
3721Expression* Parser::ParseV8Intrinsic(bool* ok) {
3722 // CallRuntime ::
3723 // '%' Identifier Arguments
3724
3725 Expect(Token::MOD, CHECK_OK);
3726 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003727 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003728
3729 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003730 // The extension structures are only accessible while parsing the
3731 // very first time not when reparsing because of lazy compilation.
3732 top_scope_->ForceEagerCompilation();
3733 }
3734
Steve Block44f0eee2011-05-26 01:26:41 +01003735 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003736
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003737 // Check for built-in IS_VAR macro.
3738 if (function != NULL &&
3739 function->intrinsic_type == Runtime::RUNTIME &&
3740 function->function_id == Runtime::kIS_VAR) {
3741 // %IS_VAR(x) evaluates to x if x is a variable,
3742 // leads to a parse error otherwise. Could be implemented as an
3743 // inline function %_IS_VAR(x) to eliminate this special case.
3744 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3745 return args->at(0);
3746 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003747 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003748 *ok = false;
3749 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003750 }
3751 }
3752
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003753 // Check that the expected number of arguments are being passed.
3754 if (function != NULL &&
3755 function->nargs != -1 &&
3756 function->nargs != args->length()) {
3757 ReportMessage("illegal_access", Vector<const char*>::empty());
3758 *ok = false;
3759 return NULL;
3760 }
3761
3762 // We have a valid intrinsics call or a call to a builtin.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003763 return new(zone()) CallRuntime(name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003764}
3765
3766
Steve Block1e0659c2011-05-24 12:43:12 +01003767bool Parser::peek_any_identifier() {
3768 Token::Value next = peek();
3769 return next == Token::IDENTIFIER ||
3770 next == Token::FUTURE_RESERVED_WORD;
3771}
3772
3773
Steve Blocka7e24c12009-10-30 11:49:00 +00003774void Parser::Consume(Token::Value token) {
3775 Token::Value next = Next();
3776 USE(next);
3777 USE(token);
3778 ASSERT(next == token);
3779}
3780
3781
3782void Parser::Expect(Token::Value token, bool* ok) {
3783 Token::Value next = Next();
3784 if (next == token) return;
3785 ReportUnexpectedToken(next);
3786 *ok = false;
3787}
3788
3789
Leon Clarke4515c472010-02-03 11:58:03 +00003790bool Parser::Check(Token::Value token) {
3791 Token::Value next = peek();
3792 if (next == token) {
3793 Consume(next);
3794 return true;
3795 }
3796 return false;
3797}
3798
3799
Steve Blocka7e24c12009-10-30 11:49:00 +00003800void Parser::ExpectSemicolon(bool* ok) {
3801 // Check for automatic semicolon insertion according to
3802 // the rules given in ECMA-262, section 7.9, page 21.
3803 Token::Value tok = peek();
3804 if (tok == Token::SEMICOLON) {
3805 Next();
3806 return;
3807 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003808 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003809 tok == Token::RBRACE ||
3810 tok == Token::EOS) {
3811 return;
3812 }
3813 Expect(Token::SEMICOLON, ok);
3814}
3815
3816
3817Literal* Parser::GetLiteralUndefined() {
Ben Murdoch8b112d22011-06-08 16:22:53 +01003818 return new(zone()) Literal(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003819}
3820
3821
3822Literal* Parser::GetLiteralTheHole() {
Ben Murdoch8b112d22011-06-08 16:22:53 +01003823 return new(zone()) Literal(isolate()->factory()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003824}
3825
3826
3827Literal* Parser::GetLiteralNumber(double value) {
3828 return NewNumberLiteral(value);
3829}
3830
3831
3832Handle<String> Parser::ParseIdentifier(bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003833 bool is_reserved;
3834 return ParseIdentifierOrReservedWord(&is_reserved, ok);
3835}
3836
3837
3838Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved,
3839 bool* ok) {
3840 *is_reserved = false;
Steve Block44f0eee2011-05-26 01:26:41 +01003841 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003842 Expect(Token::IDENTIFIER, ok);
3843 } else {
3844 if (!Check(Token::IDENTIFIER)) {
3845 Expect(Token::FUTURE_RESERVED_WORD, ok);
3846 *is_reserved = true;
3847 }
3848 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003849 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003850 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003851}
3852
Ben Murdochbb769b22010-08-11 14:56:33 +01003853
3854Handle<String> Parser::ParseIdentifierName(bool* ok) {
3855 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01003856 if (next != Token::IDENTIFIER &&
3857 next != Token::FUTURE_RESERVED_WORD &&
3858 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01003859 ReportUnexpectedToken(next);
3860 *ok = false;
3861 return Handle<String>();
3862 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003863 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01003864}
3865
3866
Steve Block1e0659c2011-05-24 12:43:12 +01003867// Checks LHS expression for assignment and prefix/postfix increment/decrement
3868// in strict mode.
3869void Parser::CheckStrictModeLValue(Expression* expression,
3870 const char* error,
3871 bool* ok) {
Steve Block44f0eee2011-05-26 01:26:41 +01003872 ASSERT(top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003873 VariableProxy* lhs = expression != NULL
3874 ? expression->AsVariableProxy()
3875 : NULL;
3876
3877 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
3878 ReportMessage(error, Vector<const char*>::empty());
3879 *ok = false;
3880 }
3881}
3882
3883
Ben Murdoch257744e2011-11-30 15:57:28 +00003884// Checks whether an octal literal was last seen between beg_pos and end_pos.
3885// If so, reports an error. Only called for strict mode.
Steve Block1e0659c2011-05-24 12:43:12 +01003886void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003887 Scanner::Location octal = scanner().octal_position();
3888 if (octal.IsValid() &&
3889 beg_pos <= octal.beg_pos &&
3890 octal.end_pos <= end_pos) {
3891 ReportMessageAt(octal, "strict_octal_literal",
Steve Block1e0659c2011-05-24 12:43:12 +01003892 Vector<const char*>::empty());
3893 scanner().clear_octal_position();
3894 *ok = false;
3895 }
3896}
3897
3898
Steve Blocka7e24c12009-10-30 11:49:00 +00003899// This function reads an identifier and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01003900// is 'get' or 'set'.
Steve Blocka7e24c12009-10-30 11:49:00 +00003901Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3902 bool* is_set,
3903 bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003904 Handle<String> result = ParseIdentifier(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003905 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01003906 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
3907 const char* token = scanner().literal_ascii_string().start();
3908 *is_get = strncmp(token, "get", 3) == 0;
3909 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003910 }
Steve Block1e0659c2011-05-24 12:43:12 +01003911 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003912}
3913
3914
3915// ----------------------------------------------------------------------------
3916// Parser support
3917
3918
3919bool Parser::TargetStackContainsLabel(Handle<String> label) {
3920 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3921 BreakableStatement* stat = t->node()->AsBreakableStatement();
3922 if (stat != NULL && ContainsLabel(stat->labels(), label))
3923 return true;
3924 }
3925 return false;
3926}
3927
3928
3929BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3930 bool anonymous = label.is_null();
3931 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3932 BreakableStatement* stat = t->node()->AsBreakableStatement();
3933 if (stat == NULL) continue;
3934 if ((anonymous && stat->is_target_for_anonymous()) ||
3935 (!anonymous && ContainsLabel(stat->labels(), label))) {
3936 RegisterTargetUse(stat->break_target(), t->previous());
3937 return stat;
3938 }
3939 }
3940 return NULL;
3941}
3942
3943
3944IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3945 bool* ok) {
3946 bool anonymous = label.is_null();
3947 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3948 IterationStatement* stat = t->node()->AsIterationStatement();
3949 if (stat == NULL) continue;
3950
3951 ASSERT(stat->is_target_for_anonymous());
3952 if (anonymous || ContainsLabel(stat->labels(), label)) {
3953 RegisterTargetUse(stat->continue_target(), t->previous());
3954 return stat;
3955 }
3956 }
3957 return NULL;
3958}
3959
3960
Ben Murdoch8b112d22011-06-08 16:22:53 +01003961void Parser::RegisterTargetUse(Label* target, Target* stop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003962 // Register that a break target found at the given stop in the
3963 // target stack has been used from the top of the target stack. Add
3964 // the break target to any TargetCollectors passed on the stack.
3965 for (Target* t = target_stack_; t != stop; t = t->previous()) {
3966 TargetCollector* collector = t->node()->AsTargetCollector();
3967 if (collector != NULL) collector->AddTarget(target);
3968 }
3969}
3970
3971
3972Literal* Parser::NewNumberLiteral(double number) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01003973 return new(zone()) Literal(isolate()->factory()->NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00003974}
3975
3976
3977Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01003978 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00003979 type, HandleVector<Object>(NULL, 0));
3980}
3981
3982
3983Expression* Parser::NewThrowSyntaxError(Handle<String> type,
3984 Handle<Object> first) {
3985 int argc = first.is_null() ? 0 : 1;
3986 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01003987 return NewThrowError(
3988 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00003989}
3990
3991
3992Expression* Parser::NewThrowTypeError(Handle<String> type,
3993 Handle<Object> first,
3994 Handle<Object> second) {
3995 ASSERT(!first.is_null() && !second.is_null());
3996 Handle<Object> elements[] = { first, second };
3997 Vector< Handle<Object> > arguments =
3998 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01003999 return NewThrowError(
4000 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004001}
4002
4003
4004Expression* Parser::NewThrowError(Handle<String> constructor,
4005 Handle<String> type,
4006 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004007 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01004008 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
4009 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004010 for (int i = 0; i < argc; i++) {
4011 Handle<Object> element = arguments[i];
4012 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01004013 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00004014 }
4015 }
Steve Block44f0eee2011-05-26 01:26:41 +01004016 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
4017 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01004018
Ben Murdoch257744e2011-11-30 15:57:28 +00004019 ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004020 args->Add(new(zone()) Literal(type));
4021 args->Add(new(zone()) Literal(array));
4022 return new(zone()) Throw(new(zone()) CallRuntime(constructor, NULL, args),
Steve Blocka7e24c12009-10-30 11:49:00 +00004023 scanner().location().beg_pos);
4024}
4025
Leon Clarke4515c472010-02-03 11:58:03 +00004026// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004027// Regular expressions
4028
4029
4030RegExpParser::RegExpParser(FlatStringReader* in,
4031 Handle<String>* error,
4032 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004033 : isolate_(Isolate::Current()),
4034 error_(error),
4035 captures_(NULL),
4036 in_(in),
4037 current_(kEndMarker),
4038 next_pos_(0),
4039 capture_count_(0),
4040 has_more_(true),
4041 multiline_(multiline),
4042 simple_(false),
4043 contains_anchor_(false),
4044 is_scanned_for_captures_(false),
4045 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004046 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004047}
4048
4049
4050uc32 RegExpParser::Next() {
4051 if (has_next()) {
4052 return in()->Get(next_pos_);
4053 } else {
4054 return kEndMarker;
4055 }
4056}
4057
4058
4059void RegExpParser::Advance() {
4060 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004061 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004062 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004063 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4064 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004065 ReportError(CStrVector("Regular expression too large"));
4066 } else {
4067 current_ = in()->Get(next_pos_);
4068 next_pos_++;
4069 }
4070 } else {
4071 current_ = kEndMarker;
4072 has_more_ = false;
4073 }
4074}
4075
4076
4077void RegExpParser::Reset(int pos) {
4078 next_pos_ = pos;
4079 Advance();
4080}
4081
4082
4083void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004084 next_pos_ += dist - 1;
4085 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004086}
4087
4088
4089bool RegExpParser::simple() {
4090 return simple_;
4091}
4092
4093RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4094 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004095 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004096 // Zip to the end to make sure the no more input is read.
4097 current_ = kEndMarker;
4098 next_pos_ = in()->length();
4099 return NULL;
4100}
4101
4102
4103// Pattern ::
4104// Disjunction
4105RegExpTree* RegExpParser::ParsePattern() {
4106 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4107 ASSERT(!has_more());
4108 // If the result of parsing is a literal string atom, and it has the
4109 // same length as the input, then the atom is identical to the input.
4110 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4111 simple_ = true;
4112 }
4113 return result;
4114}
4115
4116
4117// Disjunction ::
4118// Alternative
4119// Alternative | Disjunction
4120// Alternative ::
4121// [empty]
4122// Term Alternative
4123// Term ::
4124// Assertion
4125// Atom
4126// Atom Quantifier
4127RegExpTree* RegExpParser::ParseDisjunction() {
4128 // Used to store current state while parsing subexpressions.
4129 RegExpParserState initial_state(NULL, INITIAL, 0);
4130 RegExpParserState* stored_state = &initial_state;
4131 // Cache the builder in a local variable for quick access.
4132 RegExpBuilder* builder = initial_state.builder();
4133 while (true) {
4134 switch (current()) {
4135 case kEndMarker:
4136 if (stored_state->IsSubexpression()) {
4137 // Inside a parenthesized group when hitting end of input.
4138 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4139 }
4140 ASSERT_EQ(INITIAL, stored_state->group_type());
4141 // Parsing completed successfully.
4142 return builder->ToRegExp();
4143 case ')': {
4144 if (!stored_state->IsSubexpression()) {
4145 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4146 }
4147 ASSERT_NE(INITIAL, stored_state->group_type());
4148
4149 Advance();
4150 // End disjunction parsing and convert builder content to new single
4151 // regexp atom.
4152 RegExpTree* body = builder->ToRegExp();
4153
4154 int end_capture_index = captures_started();
4155
4156 int capture_index = stored_state->capture_index();
4157 SubexpressionType type = stored_state->group_type();
4158
4159 // Restore previous state.
4160 stored_state = stored_state->previous_state();
4161 builder = stored_state->builder();
4162
4163 // Build result of subexpression.
4164 if (type == CAPTURE) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01004165 RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004166 captures_->at(capture_index - 1) = capture;
4167 body = capture;
4168 } else if (type != GROUPING) {
4169 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4170 bool is_positive = (type == POSITIVE_LOOKAHEAD);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004171 body = new(zone()) RegExpLookahead(body,
Steve Blocka7e24c12009-10-30 11:49:00 +00004172 is_positive,
4173 end_capture_index - capture_index,
4174 capture_index);
4175 }
4176 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004177 // For compatability with JSC and ES3, we allow quantifiers after
4178 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004179 break;
4180 }
4181 case '|': {
4182 Advance();
4183 builder->NewAlternative();
4184 continue;
4185 }
4186 case '*':
4187 case '+':
4188 case '?':
4189 return ReportError(CStrVector("Nothing to repeat"));
4190 case '^': {
4191 Advance();
4192 if (multiline_) {
4193 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004194 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
Steve Blocka7e24c12009-10-30 11:49:00 +00004195 } else {
4196 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004197 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
Steve Blocka7e24c12009-10-30 11:49:00 +00004198 set_contains_anchor();
4199 }
4200 continue;
4201 }
4202 case '$': {
4203 Advance();
4204 RegExpAssertion::Type type =
4205 multiline_ ? RegExpAssertion::END_OF_LINE :
4206 RegExpAssertion::END_OF_INPUT;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004207 builder->AddAssertion(new(zone()) RegExpAssertion(type));
Steve Blocka7e24c12009-10-30 11:49:00 +00004208 continue;
4209 }
4210 case '.': {
4211 Advance();
4212 // everything except \x0a, \x0d, \u2028 and \u2029
Ben Murdoch257744e2011-11-30 15:57:28 +00004213 ZoneList<CharacterRange>* ranges =
4214 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004215 CharacterRange::AddClassEscape('.', ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004216 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004217 builder->AddAtom(atom);
4218 break;
4219 }
4220 case '(': {
4221 SubexpressionType type = CAPTURE;
4222 Advance();
4223 if (current() == '?') {
4224 switch (Next()) {
4225 case ':':
4226 type = GROUPING;
4227 break;
4228 case '=':
4229 type = POSITIVE_LOOKAHEAD;
4230 break;
4231 case '!':
4232 type = NEGATIVE_LOOKAHEAD;
4233 break;
4234 default:
4235 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4236 break;
4237 }
4238 Advance(2);
4239 } else {
4240 if (captures_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004241 captures_ = new(zone()) ZoneList<RegExpCapture*>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004242 }
4243 if (captures_started() >= kMaxCaptures) {
4244 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4245 }
4246 captures_->Add(NULL);
4247 }
4248 // Store current state and begin new disjunction parsing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004249 stored_state = new(zone()) RegExpParserState(stored_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00004250 type,
4251 captures_started());
4252 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004253 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004254 }
4255 case '[': {
4256 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4257 builder->AddAtom(atom);
4258 break;
4259 }
4260 // Atom ::
4261 // \ AtomEscape
4262 case '\\':
4263 switch (Next()) {
4264 case kEndMarker:
4265 return ReportError(CStrVector("\\ at end of pattern"));
4266 case 'b':
4267 Advance(2);
4268 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004269 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004270 continue;
4271 case 'B':
4272 Advance(2);
4273 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004274 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004275 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004276 // AtomEscape ::
4277 // CharacterClassEscape
4278 //
4279 // CharacterClassEscape :: one of
4280 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004281 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4282 uc32 c = Next();
4283 Advance(2);
Ben Murdoch257744e2011-11-30 15:57:28 +00004284 ZoneList<CharacterRange>* ranges =
4285 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004286 CharacterRange::AddClassEscape(c, ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004287 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004288 builder->AddAtom(atom);
4289 break;
4290 }
4291 case '1': case '2': case '3': case '4': case '5': case '6':
4292 case '7': case '8': case '9': {
4293 int index = 0;
4294 if (ParseBackReferenceIndex(&index)) {
4295 RegExpCapture* capture = NULL;
4296 if (captures_ != NULL && index <= captures_->length()) {
4297 capture = captures_->at(index - 1);
4298 }
4299 if (capture == NULL) {
4300 builder->AddEmpty();
4301 break;
4302 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004303 RegExpTree* atom = new(zone()) RegExpBackReference(capture);
Steve Blocka7e24c12009-10-30 11:49:00 +00004304 builder->AddAtom(atom);
4305 break;
4306 }
4307 uc32 first_digit = Next();
4308 if (first_digit == '8' || first_digit == '9') {
4309 // Treat as identity escape
4310 builder->AddCharacter(first_digit);
4311 Advance(2);
4312 break;
4313 }
4314 }
4315 // FALLTHROUGH
4316 case '0': {
4317 Advance();
4318 uc32 octal = ParseOctalLiteral();
4319 builder->AddCharacter(octal);
4320 break;
4321 }
4322 // ControlEscape :: one of
4323 // f n r t v
4324 case 'f':
4325 Advance(2);
4326 builder->AddCharacter('\f');
4327 break;
4328 case 'n':
4329 Advance(2);
4330 builder->AddCharacter('\n');
4331 break;
4332 case 'r':
4333 Advance(2);
4334 builder->AddCharacter('\r');
4335 break;
4336 case 't':
4337 Advance(2);
4338 builder->AddCharacter('\t');
4339 break;
4340 case 'v':
4341 Advance(2);
4342 builder->AddCharacter('\v');
4343 break;
4344 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004345 Advance();
4346 uc32 controlLetter = Next();
4347 // Special case if it is an ASCII letter.
4348 // Convert lower case letters to uppercase.
4349 uc32 letter = controlLetter & ~('a' ^ 'A');
4350 if (letter < 'A' || 'Z' < letter) {
4351 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4352 // This is outside the specification. We match JSC in
4353 // reading the backslash as a literal character instead
4354 // of as starting an escape.
4355 builder->AddCharacter('\\');
4356 } else {
4357 Advance(2);
4358 builder->AddCharacter(controlLetter & 0x1f);
4359 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004360 break;
4361 }
4362 case 'x': {
4363 Advance(2);
4364 uc32 value;
4365 if (ParseHexEscape(2, &value)) {
4366 builder->AddCharacter(value);
4367 } else {
4368 builder->AddCharacter('x');
4369 }
4370 break;
4371 }
4372 case 'u': {
4373 Advance(2);
4374 uc32 value;
4375 if (ParseHexEscape(4, &value)) {
4376 builder->AddCharacter(value);
4377 } else {
4378 builder->AddCharacter('u');
4379 }
4380 break;
4381 }
4382 default:
4383 // Identity escape.
4384 builder->AddCharacter(Next());
4385 Advance(2);
4386 break;
4387 }
4388 break;
4389 case '{': {
4390 int dummy;
4391 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4392 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4393 }
4394 // fallthrough
4395 }
4396 default:
4397 builder->AddCharacter(current());
4398 Advance();
4399 break;
4400 } // end switch(current())
4401
4402 int min;
4403 int max;
4404 switch (current()) {
4405 // QuantifierPrefix ::
4406 // *
4407 // +
4408 // ?
4409 // {
4410 case '*':
4411 min = 0;
4412 max = RegExpTree::kInfinity;
4413 Advance();
4414 break;
4415 case '+':
4416 min = 1;
4417 max = RegExpTree::kInfinity;
4418 Advance();
4419 break;
4420 case '?':
4421 min = 0;
4422 max = 1;
4423 Advance();
4424 break;
4425 case '{':
4426 if (ParseIntervalQuantifier(&min, &max)) {
4427 if (max < min) {
4428 ReportError(CStrVector("numbers out of order in {} quantifier.")
4429 CHECK_FAILED);
4430 }
4431 break;
4432 } else {
4433 continue;
4434 }
4435 default:
4436 continue;
4437 }
Leon Clarkee46be812010-01-19 14:06:41 +00004438 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004439 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004440 type = RegExpQuantifier::NON_GREEDY;
4441 Advance();
4442 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4443 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4444 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004445 Advance();
4446 }
Leon Clarkee46be812010-01-19 14:06:41 +00004447 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004448 }
4449}
4450
Steve Blocka7e24c12009-10-30 11:49:00 +00004451
4452#ifdef DEBUG
4453// Currently only used in an ASSERT.
4454static bool IsSpecialClassEscape(uc32 c) {
4455 switch (c) {
4456 case 'd': case 'D':
4457 case 's': case 'S':
4458 case 'w': case 'W':
4459 return true;
4460 default:
4461 return false;
4462 }
4463}
4464#endif
4465
4466
4467// In order to know whether an escape is a backreference or not we have to scan
4468// the entire regexp and find the number of capturing parentheses. However we
4469// don't want to scan the regexp twice unless it is necessary. This mini-parser
4470// is called when needed. It can see the difference between capturing and
4471// noncapturing parentheses and can skip character classes and backslash-escaped
4472// characters.
4473void RegExpParser::ScanForCaptures() {
4474 // Start with captures started previous to current position
4475 int capture_count = captures_started();
4476 // Add count of captures after this position.
4477 int n;
4478 while ((n = current()) != kEndMarker) {
4479 Advance();
4480 switch (n) {
4481 case '\\':
4482 Advance();
4483 break;
4484 case '[': {
4485 int c;
4486 while ((c = current()) != kEndMarker) {
4487 Advance();
4488 if (c == '\\') {
4489 Advance();
4490 } else {
4491 if (c == ']') break;
4492 }
4493 }
4494 break;
4495 }
4496 case '(':
4497 if (current() != '?') capture_count++;
4498 break;
4499 }
4500 }
4501 capture_count_ = capture_count;
4502 is_scanned_for_captures_ = true;
4503}
4504
4505
4506bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4507 ASSERT_EQ('\\', current());
4508 ASSERT('1' <= Next() && Next() <= '9');
4509 // Try to parse a decimal literal that is no greater than the total number
4510 // of left capturing parentheses in the input.
4511 int start = position();
4512 int value = Next() - '0';
4513 Advance(2);
4514 while (true) {
4515 uc32 c = current();
4516 if (IsDecimalDigit(c)) {
4517 value = 10 * value + (c - '0');
4518 if (value > kMaxCaptures) {
4519 Reset(start);
4520 return false;
4521 }
4522 Advance();
4523 } else {
4524 break;
4525 }
4526 }
4527 if (value > captures_started()) {
4528 if (!is_scanned_for_captures_) {
4529 int saved_position = position();
4530 ScanForCaptures();
4531 Reset(saved_position);
4532 }
4533 if (value > capture_count_) {
4534 Reset(start);
4535 return false;
4536 }
4537 }
4538 *index_out = value;
4539 return true;
4540}
4541
4542
4543// QuantifierPrefix ::
4544// { DecimalDigits }
4545// { DecimalDigits , }
4546// { DecimalDigits , DecimalDigits }
4547//
4548// Returns true if parsing succeeds, and set the min_out and max_out
4549// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4550bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4551 ASSERT_EQ(current(), '{');
4552 int start = position();
4553 Advance();
4554 int min = 0;
4555 if (!IsDecimalDigit(current())) {
4556 Reset(start);
4557 return false;
4558 }
4559 while (IsDecimalDigit(current())) {
4560 int next = current() - '0';
4561 if (min > (RegExpTree::kInfinity - next) / 10) {
4562 // Overflow. Skip past remaining decimal digits and return -1.
4563 do {
4564 Advance();
4565 } while (IsDecimalDigit(current()));
4566 min = RegExpTree::kInfinity;
4567 break;
4568 }
4569 min = 10 * min + next;
4570 Advance();
4571 }
4572 int max = 0;
4573 if (current() == '}') {
4574 max = min;
4575 Advance();
4576 } else if (current() == ',') {
4577 Advance();
4578 if (current() == '}') {
4579 max = RegExpTree::kInfinity;
4580 Advance();
4581 } else {
4582 while (IsDecimalDigit(current())) {
4583 int next = current() - '0';
4584 if (max > (RegExpTree::kInfinity - next) / 10) {
4585 do {
4586 Advance();
4587 } while (IsDecimalDigit(current()));
4588 max = RegExpTree::kInfinity;
4589 break;
4590 }
4591 max = 10 * max + next;
4592 Advance();
4593 }
4594 if (current() != '}') {
4595 Reset(start);
4596 return false;
4597 }
4598 Advance();
4599 }
4600 } else {
4601 Reset(start);
4602 return false;
4603 }
4604 *min_out = min;
4605 *max_out = max;
4606 return true;
4607}
4608
4609
Steve Blocka7e24c12009-10-30 11:49:00 +00004610uc32 RegExpParser::ParseOctalLiteral() {
4611 ASSERT('0' <= current() && current() <= '7');
4612 // For compatibility with some other browsers (not all), we parse
4613 // up to three octal digits with a value below 256.
4614 uc32 value = current() - '0';
4615 Advance();
4616 if ('0' <= current() && current() <= '7') {
4617 value = value * 8 + current() - '0';
4618 Advance();
4619 if (value < 32 && '0' <= current() && current() <= '7') {
4620 value = value * 8 + current() - '0';
4621 Advance();
4622 }
4623 }
4624 return value;
4625}
4626
4627
4628bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4629 int start = position();
4630 uc32 val = 0;
4631 bool done = false;
4632 for (int i = 0; !done; i++) {
4633 uc32 c = current();
4634 int d = HexValue(c);
4635 if (d < 0) {
4636 Reset(start);
4637 return false;
4638 }
4639 val = val * 16 + d;
4640 Advance();
4641 if (i == length - 1) {
4642 done = true;
4643 }
4644 }
4645 *value = val;
4646 return true;
4647}
4648
4649
4650uc32 RegExpParser::ParseClassCharacterEscape() {
4651 ASSERT(current() == '\\');
4652 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4653 Advance();
4654 switch (current()) {
4655 case 'b':
4656 Advance();
4657 return '\b';
4658 // ControlEscape :: one of
4659 // f n r t v
4660 case 'f':
4661 Advance();
4662 return '\f';
4663 case 'n':
4664 Advance();
4665 return '\n';
4666 case 'r':
4667 Advance();
4668 return '\r';
4669 case 't':
4670 Advance();
4671 return '\t';
4672 case 'v':
4673 Advance();
4674 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004675 case 'c': {
4676 uc32 controlLetter = Next();
4677 uc32 letter = controlLetter & ~('A' ^ 'a');
4678 // For compatibility with JSC, inside a character class
4679 // we also accept digits and underscore as control characters.
4680 if ((controlLetter >= '0' && controlLetter <= '9') ||
4681 controlLetter == '_' ||
4682 (letter >= 'A' && letter <= 'Z')) {
4683 Advance(2);
4684 // Control letters mapped to ASCII control characters in the range
4685 // 0x00-0x1f.
4686 return controlLetter & 0x1f;
4687 }
4688 // We match JSC in reading the backslash as a literal
4689 // character instead of as starting an escape.
4690 return '\\';
4691 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004692 case '0': case '1': case '2': case '3': case '4': case '5':
4693 case '6': case '7':
4694 // For compatibility, we interpret a decimal escape that isn't
4695 // a back reference (and therefore either \0 or not valid according
4696 // to the specification) as a 1..3 digit octal character code.
4697 return ParseOctalLiteral();
4698 case 'x': {
4699 Advance();
4700 uc32 value;
4701 if (ParseHexEscape(2, &value)) {
4702 return value;
4703 }
4704 // If \x is not followed by a two-digit hexadecimal, treat it
4705 // as an identity escape.
4706 return 'x';
4707 }
4708 case 'u': {
4709 Advance();
4710 uc32 value;
4711 if (ParseHexEscape(4, &value)) {
4712 return value;
4713 }
4714 // If \u is not followed by a four-digit hexadecimal, treat it
4715 // as an identity escape.
4716 return 'u';
4717 }
4718 default: {
4719 // Extended identity escape. We accept any character that hasn't
4720 // been matched by a more specific case, not just the subset required
4721 // by the ECMAScript specification.
4722 uc32 result = current();
4723 Advance();
4724 return result;
4725 }
4726 }
4727 return 0;
4728}
4729
4730
4731CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4732 ASSERT_EQ(0, *char_class);
4733 uc32 first = current();
4734 if (first == '\\') {
4735 switch (Next()) {
4736 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4737 *char_class = Next();
4738 Advance(2);
4739 return CharacterRange::Singleton(0); // Return dummy value.
4740 }
4741 case kEndMarker:
4742 return ReportError(CStrVector("\\ at end of pattern"));
4743 default:
4744 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4745 return CharacterRange::Singleton(c);
4746 }
4747 } else {
4748 Advance();
4749 return CharacterRange::Singleton(first);
4750 }
4751}
4752
4753
Ben Murdochb0fe1622011-05-05 13:52:32 +01004754static const uc16 kNoCharClass = 0;
4755
4756// Adds range or pre-defined character class to character ranges.
4757// If char_class is not kInvalidClass, it's interpreted as a class
4758// escape (i.e., 's' means whitespace, from '\s').
4759static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4760 uc16 char_class,
4761 CharacterRange range) {
4762 if (char_class != kNoCharClass) {
4763 CharacterRange::AddClassEscape(char_class, ranges);
4764 } else {
4765 ranges->Add(range);
4766 }
4767}
4768
4769
Steve Blocka7e24c12009-10-30 11:49:00 +00004770RegExpTree* RegExpParser::ParseCharacterClass() {
4771 static const char* kUnterminated = "Unterminated character class";
4772 static const char* kRangeOutOfOrder = "Range out of order in character class";
4773
4774 ASSERT_EQ(current(), '[');
4775 Advance();
4776 bool is_negated = false;
4777 if (current() == '^') {
4778 is_negated = true;
4779 Advance();
4780 }
Ben Murdoch257744e2011-11-30 15:57:28 +00004781 ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004782 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004783 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004784 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004785 if (current() == '-') {
4786 Advance();
4787 if (current() == kEndMarker) {
4788 // If we reach the end we break out of the loop and let the
4789 // following code report an error.
4790 break;
4791 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004792 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004793 ranges->Add(CharacterRange::Singleton('-'));
4794 break;
4795 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004796 uc16 char_class_2 = kNoCharClass;
4797 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4798 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4799 // Either end is an escaped character class. Treat the '-' verbatim.
4800 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004801 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004802 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004803 continue;
4804 }
4805 if (first.from() > next.to()) {
4806 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4807 }
4808 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4809 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004810 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004811 }
4812 }
4813 if (!has_more()) {
4814 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4815 }
4816 Advance();
4817 if (ranges->length() == 0) {
4818 ranges->Add(CharacterRange::Everything());
4819 is_negated = !is_negated;
4820 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004821 return new(zone()) RegExpCharacterClass(ranges, is_negated);
Steve Blocka7e24c12009-10-30 11:49:00 +00004822}
4823
4824
4825// ----------------------------------------------------------------------------
4826// The Parser interface.
4827
Steve Blocka7e24c12009-10-30 11:49:00 +00004828ParserMessage::~ParserMessage() {
4829 for (int i = 0; i < args().length(); i++)
4830 DeleteArray(args()[i]);
4831 DeleteArray(args().start());
4832}
4833
4834
4835ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01004836 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00004837}
4838
4839
4840int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01004841 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00004842}
4843
4844
Leon Clarkef7060e22010-06-03 12:02:55 +01004845const char* ScriptDataImpl::Data() {
4846 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00004847}
4848
4849
Leon Clarkee46be812010-01-19 14:06:41 +00004850bool ScriptDataImpl::HasError() {
4851 return has_error();
4852}
4853
4854
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004855void ScriptDataImpl::Initialize() {
4856 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004857 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
4858 function_index_ = PreparseDataConstants::kHeaderSize;
4859 int symbol_data_offset = PreparseDataConstants::kHeaderSize
4860 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004861 if (store_.length() > symbol_data_offset) {
4862 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
4863 } else {
4864 // Partial preparse causes no symbol information.
4865 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4866 }
4867 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4868 }
4869}
4870
4871
4872int ScriptDataImpl::ReadNumber(byte** source) {
4873 // Reads a number from symbol_data_ in base 128. The most significant
4874 // bit marks that there are more digits.
4875 // If the first byte is 0x80 (kNumberTerminator), it would normally
4876 // represent a leading zero. Since that is useless, and therefore won't
4877 // appear as the first digit of any actual value, it is used to
4878 // mark the end of the input stream.
4879 byte* data = *source;
4880 if (data >= symbol_data_end_) return -1;
4881 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004882 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004883 // End of stream marker.
4884 return -1;
4885 }
4886 int result = input & 0x7f;
4887 data++;
4888 while ((input & 0x80u) != 0) {
4889 if (data >= symbol_data_end_) return -1;
4890 input = *data;
4891 result = (result << 7) | (input & 0x7f);
4892 data++;
4893 }
4894 *source = data;
4895 return result;
4896}
4897
4898
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004899// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004900static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004901 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01004902 ParserRecorder* recorder) {
Steve Block44f0eee2011-05-26 01:26:41 +01004903 Isolate* isolate = Isolate::Current();
Ben Murdoch8b112d22011-06-08 16:22:53 +01004904 V8JavaScriptScanner scanner(isolate->unicode_cache());
Steve Block9fac8402011-05-12 15:51:54 +01004905 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01004906 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004907 if (!preparser::PreParser::PreParseProgram(&scanner,
4908 recorder,
4909 allow_lazy,
4910 stack_limit)) {
Steve Block44f0eee2011-05-26 01:26:41 +01004911 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004912 return NULL;
4913 }
4914
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004915 // Extract the accumulated data from the recorder as a single
4916 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004917 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00004918 return new ScriptDataImpl(store);
4919}
4920
4921
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004922// Preparse, but only collect data that is immediately useful,
4923// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004924ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004925 v8::Extension* extension) {
4926 bool allow_lazy = FLAG_lazy && (extension == NULL);
4927 if (!allow_lazy) {
4928 // Partial preparsing is only about lazily compiled functions.
4929 // If we don't allow lazy compilation, the log data will be empty.
4930 return NULL;
4931 }
4932 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01004933 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004934}
4935
4936
Ben Murdochb0fe1622011-05-05 13:52:32 +01004937ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004938 v8::Extension* extension) {
4939 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004940 bool allow_lazy = FLAG_lazy && (extension == NULL);
4941 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01004942 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004943}
4944
4945
4946bool RegExpParser::ParseRegExp(FlatStringReader* input,
4947 bool multiline,
4948 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004949 ASSERT(result != NULL);
4950 RegExpParser parser(input, &result->error, multiline);
4951 RegExpTree* tree = parser.ParsePattern();
4952 if (parser.failed()) {
4953 ASSERT(tree == NULL);
4954 ASSERT(!result->error.is_null());
4955 } else {
4956 ASSERT(tree != NULL);
4957 ASSERT(result->error.is_null());
4958 result->tree = tree;
4959 int capture_count = parser.captures_started();
4960 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
4961 result->contains_anchor = parser.contains_anchor();
4962 result->capture_count = capture_count;
4963 }
4964 return !parser.failed();
4965}
4966
4967
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004968bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01004969 ASSERT(info->function() == NULL);
4970 FunctionLiteral* result = NULL;
4971 Handle<Script> script = info->script();
4972 if (info->is_lazy()) {
Ben Murdoch203a29f2011-10-20 14:36:23 +01004973 bool allow_natives_syntax =
4974 FLAG_allow_natives_syntax ||
4975 info->is_native();
4976 Parser parser(script, allow_natives_syntax, NULL, NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01004977 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00004978 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01004979 bool allow_natives_syntax =
Ben Murdoch203a29f2011-10-20 14:36:23 +01004980 info->is_native() || FLAG_allow_natives_syntax;
Ben Murdochf87a2032010-10-22 12:50:53 +01004981 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004982 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01004983 if (pre_data != NULL && pre_data->has_error()) {
4984 Scanner::Location loc = pre_data->MessageLocation();
4985 const char* message = pre_data->BuildMessage();
4986 Vector<const char*> args = pre_data->BuildArgs();
4987 parser.ReportMessageAt(loc, message, args);
4988 DeleteArray(message);
4989 for (int i = 0; i < args.length(); i++) {
4990 DeleteArray(args[i]);
4991 }
4992 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01004993 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01004994 } else {
4995 Handle<String> source = Handle<String>(String::cast(script->source()));
Steve Block1e0659c2011-05-24 12:43:12 +01004996 result = parser.ParseProgram(source,
4997 info->is_global(),
4998 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01004999 }
Leon Clarke4515c472010-02-03 11:58:03 +00005000 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005001
5002 info->SetFunction(result);
5003 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005004}
5005
Steve Blocka7e24c12009-10-30 11:49:00 +00005006} } // namespace v8::internal