blob: cf84bfab3758b3be6e81fd490f388c5a3aed1c5a [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"
31#include "ast.h"
32#include "bootstrapper.h"
Steve Block6ded16b2010-05-10 14:33:55 +010033#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010035#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010036#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010037#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080039#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "runtime.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010041#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "string-stream.h"
43
Kristian Monsen25f61362010-05-21 11:50:48 +010044#include "ast-inl.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010045
Steve Blocka7e24c12009-10-30 11:49:00 +000046namespace v8 {
47namespace internal {
48
Steve Blocka7e24c12009-10-30 11:49:00 +000049// PositionStack is used for on-stack allocation of token positions for
50// new expressions. Please look at ParseNewExpression.
51
52class PositionStack {
53 public:
54 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
55 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
56
57 class Element {
58 public:
59 Element(PositionStack* stack, int value) {
60 previous_ = stack->top();
61 value_ = value;
62 stack->set_top(this);
63 }
64
65 private:
66 Element* previous() { return previous_; }
67 int value() { return value_; }
68 friend class PositionStack;
69 Element* previous_;
70 int value_;
71 };
72
73 bool is_empty() { return top_ == NULL; }
74 int pop() {
75 ASSERT(!is_empty());
76 int result = top_->value();
77 top_ = top_->previous();
78 return result;
79 }
80
81 private:
82 Element* top() { return top_; }
83 void set_top(Element* value) { top_ = value; }
84 Element* top_;
85 bool* ok_;
86};
87
88
Steve Blocka7e24c12009-10-30 11:49:00 +000089RegExpBuilder::RegExpBuilder()
Ben Murdoch8b112d22011-06-08 16:22:53 +010090 : zone_(Isolate::Current()->zone()),
91 pending_empty_(false),
92 characters_(NULL),
93 terms_(),
94 alternatives_()
Steve Blocka7e24c12009-10-30 11:49:00 +000095#ifdef DEBUG
Ben Murdoch8b112d22011-06-08 16:22:53 +010096 , last_added_(ADD_NONE)
Steve Blocka7e24c12009-10-30 11:49:00 +000097#endif
98 {}
99
100
101void RegExpBuilder::FlushCharacters() {
102 pending_empty_ = false;
103 if (characters_ != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100104 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
Steve Blocka7e24c12009-10-30 11:49:00 +0000105 characters_ = NULL;
106 text_.Add(atom);
107 LAST(ADD_ATOM);
108 }
109}
110
111
112void RegExpBuilder::FlushText() {
113 FlushCharacters();
114 int num_text = text_.length();
115 if (num_text == 0) {
116 return;
117 } else if (num_text == 1) {
118 terms_.Add(text_.last());
119 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100120 RegExpText* text = new(zone()) RegExpText();
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 for (int i = 0; i < num_text; i++)
122 text_.Get(i)->AppendToText(text);
123 terms_.Add(text);
124 }
125 text_.Clear();
126}
127
128
129void RegExpBuilder::AddCharacter(uc16 c) {
130 pending_empty_ = false;
131 if (characters_ == NULL) {
132 characters_ = new ZoneList<uc16>(4);
133 }
134 characters_->Add(c);
135 LAST(ADD_CHAR);
136}
137
138
139void RegExpBuilder::AddEmpty() {
140 pending_empty_ = true;
141}
142
143
144void RegExpBuilder::AddAtom(RegExpTree* term) {
145 if (term->IsEmpty()) {
146 AddEmpty();
147 return;
148 }
149 if (term->IsTextElement()) {
150 FlushCharacters();
151 text_.Add(term);
152 } else {
153 FlushText();
154 terms_.Add(term);
155 }
156 LAST(ADD_ATOM);
157}
158
159
160void RegExpBuilder::AddAssertion(RegExpTree* assert) {
161 FlushText();
162 terms_.Add(assert);
163 LAST(ADD_ASSERT);
164}
165
166
167void RegExpBuilder::NewAlternative() {
168 FlushTerms();
169}
170
171
172void RegExpBuilder::FlushTerms() {
173 FlushText();
174 int num_terms = terms_.length();
175 RegExpTree* alternative;
176 if (num_terms == 0) {
177 alternative = RegExpEmpty::GetInstance();
178 } else if (num_terms == 1) {
179 alternative = terms_.last();
180 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100181 alternative = new(zone()) RegExpAlternative(terms_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 }
183 alternatives_.Add(alternative);
184 terms_.Clear();
185 LAST(ADD_NONE);
186}
187
188
189RegExpTree* RegExpBuilder::ToRegExp() {
190 FlushTerms();
191 int num_alternatives = alternatives_.length();
192 if (num_alternatives == 0) {
193 return RegExpEmpty::GetInstance();
194 }
195 if (num_alternatives == 1) {
196 return alternatives_.last();
197 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100198 return new(zone()) RegExpDisjunction(alternatives_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000199}
200
201
Leon Clarkee46be812010-01-19 14:06:41 +0000202void RegExpBuilder::AddQuantifierToAtom(int min,
203 int max,
204 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (pending_empty_) {
206 pending_empty_ = false;
207 return;
208 }
209 RegExpTree* atom;
210 if (characters_ != NULL) {
211 ASSERT(last_added_ == ADD_CHAR);
212 // Last atom was character.
213 Vector<const uc16> char_vector = characters_->ToConstVector();
214 int num_chars = char_vector.length();
215 if (num_chars > 1) {
216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100217 text_.Add(new(zone()) RegExpAtom(prefix));
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219 }
220 characters_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100221 atom = new(zone()) RegExpAtom(char_vector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000222 FlushText();
223 } else if (text_.length() > 0) {
224 ASSERT(last_added_ == ADD_ATOM);
225 atom = text_.RemoveLast();
226 FlushText();
227 } else if (terms_.length() > 0) {
228 ASSERT(last_added_ == ADD_ATOM);
229 atom = terms_.RemoveLast();
230 if (atom->max_match() == 0) {
231 // Guaranteed to only match an empty string.
232 LAST(ADD_TERM);
233 if (min == 0) {
234 return;
235 }
236 terms_.Add(atom);
237 return;
238 }
239 } else {
240 // Only call immediately after adding an atom or character!
241 UNREACHABLE();
242 return;
243 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100244 terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 LAST(ADD_TERM);
246}
247
248
Steve Block9fac8402011-05-12 15:51:54 +0100249Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800250 // Length of symbol cache is the number of identified symbols.
251 // If we are larger than that, or negative, it's not a cached symbol.
252 // This might also happen if there is no preparser symbol data, even
253 // if there is some preparser data.
254 if (static_cast<unsigned>(symbol_id)
255 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100256 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100257 return isolate()->factory()->LookupAsciiSymbol(
258 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100259 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100260 return isolate()->factory()->LookupTwoByteSymbol(
261 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100262 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800263 }
Steve Block9fac8402011-05-12 15:51:54 +0100264 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800265}
266
267
Steve Block9fac8402011-05-12 15:51:54 +0100268Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800269 // Make sure the cache is large enough to hold the symbol identifier.
270 if (symbol_cache_.length() <= symbol_id) {
271 // Increase length to index + 1.
272 symbol_cache_.AddBlock(Handle<String>::null(),
273 symbol_id + 1 - symbol_cache_.length());
274 }
275 Handle<String> result = symbol_cache_.at(symbol_id);
276 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100277 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100278 result = isolate()->factory()->LookupAsciiSymbol(
279 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100280 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100281 result = isolate()->factory()->LookupTwoByteSymbol(
282 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100283 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800284 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100285 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 }
Steve Block44f0eee2011-05-26 01:26:41 +0100287 isolate()->counters()->total_preparse_symbols_skipped()->Increment();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800288 return result;
289}
Steve Blocka7e24c12009-10-30 11:49:00 +0000290
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800291
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100292FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
293 // The current pre-data entry must be a FunctionEntry with the given
294 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100295 if ((function_index_ + FunctionEntry::kSize <= store_.length())
296 && (static_cast<int>(store_[function_index_]) == start)) {
297 int index = function_index_;
298 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100299 return FunctionEntry(store_.SubVector(index,
300 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000301 }
302 return FunctionEntry();
303}
304
305
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100306int ScriptDataImpl::GetSymbolIdentifier() {
307 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100308}
309
310
Iain Merrick9ac36c92010-09-13 15:29:50 +0100311bool ScriptDataImpl::SanityCheck() {
312 // Check that the header data is valid and doesn't specify
313 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800314 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
315 if (magic() != PreparseDataConstants::kMagicNumber) return false;
316 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100317 if (has_error()) {
318 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800319 if (store_.length() <= PreparseDataConstants::kHeaderSize
320 + PreparseDataConstants::kMessageTextPos) {
321 return false;
322 }
323 if (Read(PreparseDataConstants::kMessageStartPos) >
324 Read(PreparseDataConstants::kMessageEndPos)) {
325 return false;
326 }
327 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
328 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100329 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800330 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
331 return false;
332 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100333 int length = static_cast<int>(Read(pos));
334 if (length < 0) return false;
335 pos += 1 + length;
336 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800337 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
338 return false;
339 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100340 return true;
341 }
342 // Check that the space allocated for function entries is sane.
343 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800344 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100345 if (functions_size < 0) return false;
346 if (functions_size % FunctionEntry::kSize != 0) return false;
347 // Check that the count of symbols is non-negative.
348 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800349 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100350 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100351 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100352 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800353 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100354 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 return true;
356}
357
358
Steve Block59151502010-09-22 15:07:15 +0100359
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100360const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 int length = start[0];
362 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100363 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000364 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100365 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 result[length] = '\0';
367 if (chars != NULL) *chars = length;
368 return result;
369}
370
Steve Blocka7e24c12009-10-30 11:49:00 +0000371Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800372 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
373 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 return Scanner::Location(beg_pos, end_pos);
375}
376
377
378const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800379 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100380 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000381}
382
383
384Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800385 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100387 // Position after text found by skipping past length field and
388 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800389 int pos = PreparseDataConstants::kMessageTextPos + 1
390 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 for (int i = 0; i < arg_count; i++) {
392 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100393 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000394 pos += count + 1;
395 }
396 return Vector<const char*>(array, arg_count);
397}
398
399
400unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800401 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000402}
403
404
405unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800406 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000407}
408
409
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800410Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100411 Scope* result = new(zone()) Scope(parent, type);
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 result->Initialize(inside_with);
413 return result;
414}
415
Steve Blocka7e24c12009-10-30 11:49:00 +0000416// ----------------------------------------------------------------------------
417// Target is a support class to facilitate manipulation of the
418// Parser's target_stack_ (the stack of potential 'break' and
419// 'continue' statement targets). Upon construction, a new target is
420// added; it is removed upon destruction.
421
422class Target BASE_EMBEDDED {
423 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800424 Target(Target** variable, AstNode* node)
425 : variable_(variable), node_(node), previous_(*variable) {
426 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000427 }
428
429 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800430 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000431 }
432
433 Target* previous() { return previous_; }
434 AstNode* node() { return node_; }
435
436 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800437 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 AstNode* node_;
439 Target* previous_;
440};
441
442
443class TargetScope BASE_EMBEDDED {
444 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800445 explicit TargetScope(Target** variable)
446 : variable_(variable), previous_(*variable) {
447 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 }
449
450 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800451 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 }
453
454 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800455 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000456 Target* previous_;
457};
458
459
460// ----------------------------------------------------------------------------
461// LexicalScope is a support class to facilitate manipulation of the
462// Parser's scope stack. The constructor sets the parser's top scope
463// to the incoming scope, and the destructor resets it.
Steve Block44f0eee2011-05-26 01:26:41 +0100464//
Ben Murdoch8b112d22011-06-08 16:22:53 +0100465// Additionally, it stores transient information used during parsing.
Steve Block44f0eee2011-05-26 01:26:41 +0100466// These scopes are not kept around after parsing or referenced by syntax
467// trees so they can be stack-allocated and hence used by the pre-parser.
Steve Blocka7e24c12009-10-30 11:49:00 +0000468
469class LexicalScope BASE_EMBEDDED {
470 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100471 LexicalScope(Parser* parser, Scope* scope, Isolate* isolate);
472 ~LexicalScope();
473
474 int NextMaterializedLiteralIndex() {
475 int next_index =
476 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
477 materialized_literal_count_++;
478 return next_index;
479 }
480 int materialized_literal_count() { return materialized_literal_count_; }
481
482 void SetThisPropertyAssignmentInfo(
483 bool only_simple_this_property_assignments,
484 Handle<FixedArray> this_property_assignments) {
485 only_simple_this_property_assignments_ =
486 only_simple_this_property_assignments;
487 this_property_assignments_ = this_property_assignments;
488 }
489 bool only_simple_this_property_assignments() {
490 return only_simple_this_property_assignments_;
491 }
492 Handle<FixedArray> this_property_assignments() {
493 return this_property_assignments_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 }
495
Steve Block44f0eee2011-05-26 01:26:41 +0100496 void AddProperty() { expected_property_count_++; }
497 int expected_property_count() { return expected_property_count_; }
498
Steve Blocka7e24c12009-10-30 11:49:00 +0000499 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100500 // Captures the number of literals that need materialization in the
501 // function. Includes regexp literals, and boilerplate for object
502 // and array literals.
503 int materialized_literal_count_;
504
505 // Properties count estimation.
506 int expected_property_count_;
507
508 // Keeps track of assignments to properties of this. Used for
509 // optimizing constructors.
510 bool only_simple_this_property_assignments_;
511 Handle<FixedArray> this_property_assignments_;
512
Steve Block44f0eee2011-05-26 01:26:41 +0100513 // Bookkeeping
514 Parser* parser_;
515 // Previous values
516 LexicalScope* lexical_scope_parent_;
517 Scope* previous_scope_;
518 int previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100519 unsigned previous_ast_node_id_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000520};
521
Steve Block44f0eee2011-05-26 01:26:41 +0100522
523LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
524 : materialized_literal_count_(0),
525 expected_property_count_(0),
526 only_simple_this_property_assignments_(false),
527 this_property_assignments_(isolate->factory()->empty_fixed_array()),
Steve Block44f0eee2011-05-26 01:26:41 +0100528 parser_(parser),
529 lexical_scope_parent_(parser->lexical_scope_),
530 previous_scope_(parser->top_scope_),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100531 previous_with_nesting_level_(parser->with_nesting_level_),
532 previous_ast_node_id_(isolate->ast_node_id()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100533 parser->top_scope_ = scope;
534 parser->lexical_scope_ = this;
535 parser->with_nesting_level_ = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100536 isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1);
Steve Block44f0eee2011-05-26 01:26:41 +0100537}
538
539
540LexicalScope::~LexicalScope() {
541 parser_->top_scope_->Leave();
542 parser_->top_scope_ = previous_scope_;
543 parser_->lexical_scope_ = lexical_scope_parent_;
544 parser_->with_nesting_level_ = previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100545 parser_->isolate()->set_ast_node_id(previous_ast_node_id_);
Steve Block44f0eee2011-05-26 01:26:41 +0100546}
547
548
Steve Blocka7e24c12009-10-30 11:49:00 +0000549// ----------------------------------------------------------------------------
550// The CHECK_OK macro is a convenient macro to enforce error
551// handling for functions that may fail (by returning !*ok).
552//
553// CAUTION: This macro appends extra statements after a call,
554// thus it must never be used where only a single statement
555// is correct (e.g. an if statement branch w/o braces)!
556
557#define CHECK_OK ok); \
558 if (!*ok) return NULL; \
559 ((void)0
560#define DUMMY ) // to make indentation work
561#undef DUMMY
562
563#define CHECK_FAILED /**/); \
564 if (failed_) return NULL; \
565 ((void)0
566#define DUMMY ) // to make indentation work
567#undef DUMMY
568
569// ----------------------------------------------------------------------------
570// Implementation of Parser
571
572Parser::Parser(Handle<Script> script,
573 bool allow_natives_syntax,
574 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000575 ScriptDataImpl* pre_data)
Steve Block44f0eee2011-05-26 01:26:41 +0100576 : isolate_(script->GetIsolate()),
577 symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800578 script_(script),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100579 scanner_(isolate_->unicode_cache()),
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 top_scope_(NULL),
581 with_nesting_level_(0),
Steve Block44f0eee2011-05-26 01:26:41 +0100582 lexical_scope_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 target_stack_(NULL),
584 allow_natives_syntax_(allow_natives_syntax),
585 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100586 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100587 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100588 stack_overflow_(false),
589 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100590 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000591}
592
593
Steve Blocka7e24c12009-10-30 11:49:00 +0000594FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Block1e0659c2011-05-24 12:43:12 +0100595 bool in_global_context,
596 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000597 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
598
Steve Block44f0eee2011-05-26 01:26:41 +0100599 HistogramTimerScope timer(isolate()->counters()->parse());
600 isolate()->counters()->total_parse_size()->Increment(source->length());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100601 fni_ = new(zone()) FuncNameInferrer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000602
603 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100604 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100605 if (source->IsExternalTwoByteString()) {
606 // Notice that the stream is destroyed at the end of the branch block.
607 // The last line of the blocks can't be moved outside, even though they're
608 // identical calls.
609 ExternalTwoByteStringUC16CharacterStream stream(
610 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100611 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100612 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100613 } else {
614 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100615 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100616 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100617 }
618}
619
620
621FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
622 bool in_global_context,
Steve Block1e0659c2011-05-24 12:43:12 +0100623 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100624 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000625 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100626 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000627
628 // Compute the parsing mode.
629 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
630 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
631
632 Scope::Type type =
633 in_global_context
634 ? Scope::GLOBAL_SCOPE
635 : Scope::EVAL_SCOPE;
Steve Block44f0eee2011-05-26 01:26:41 +0100636 Handle<String> no_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000637
638 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800639 { Scope* scope = NewScope(top_scope_, type, inside_with());
Steve Block44f0eee2011-05-26 01:26:41 +0100640 LexicalScope lexical_scope(this, scope, isolate());
Steve Block1e0659c2011-05-24 12:43:12 +0100641 if (strict_mode == kStrictMode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100642 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100643 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800644 ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000645 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100646 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800647 ParseSourceElements(body, Token::EOS, &ok);
Steve Block44f0eee2011-05-26 01:26:41 +0100648 if (ok && top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100649 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
650 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 if (ok) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100652 result = new(zone()) FunctionLiteral(
Steve Blocka7e24c12009-10-30 11:49:00 +0000653 no_name,
654 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800655 body,
Steve Block44f0eee2011-05-26 01:26:41 +0100656 lexical_scope.materialized_literal_count(),
657 lexical_scope.expected_property_count(),
658 lexical_scope.only_simple_this_property_assignments(),
659 lexical_scope.this_property_assignments(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000660 0,
661 0,
662 source->length(),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100663 false);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 } else if (stack_overflow_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100665 isolate()->StackOverflow();
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 }
667 }
668
669 // Make sure the target stack is empty.
670 ASSERT(target_stack_ == NULL);
671
672 // If there was a syntax error we have to get rid of the AST
673 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000675 return result;
676}
677
Steve Block44f0eee2011-05-26 01:26:41 +0100678FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
Steve Block44f0eee2011-05-26 01:26:41 +0100680 HistogramTimerScope timer(isolate()->counters()->parse_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100681 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100682 isolate()->counters()->total_parse_size()->Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000683
Steve Block44f0eee2011-05-26 01:26:41 +0100684 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100685 // Initialize parser state.
686 source->TryFlatten();
687 if (source->IsExternalTwoByteString()) {
688 ExternalTwoByteStringUC16CharacterStream stream(
689 Handle<ExternalTwoByteString>::cast(source),
Steve Block44f0eee2011-05-26 01:26:41 +0100690 shared_info->start_position(),
691 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100692 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
693 return result;
694 } else {
695 GenericStringUC16CharacterStream stream(source,
Steve Block44f0eee2011-05-26 01:26:41 +0100696 shared_info->start_position(),
697 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
699 return result;
700 }
701}
702
703
Steve Block44f0eee2011-05-26 01:26:41 +0100704FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100705 UC16CharacterStream* source,
706 ZoneScope* zone_scope) {
Steve Block44f0eee2011-05-26 01:26:41 +0100707 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Steve Block9fac8402011-05-12 15:51:54 +0100708 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100709 ASSERT(target_stack_ == NULL);
710
Steve Block44f0eee2011-05-26 01:26:41 +0100711 Handle<String> name(String::cast(shared_info->name()));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100712 fni_ = new(zone()) FuncNameInferrer();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100713 fni_->PushEnclosingName(name);
714
Steve Blocka7e24c12009-10-30 11:49:00 +0000715 mode_ = PARSE_EAGERLY;
716
717 // Place holder for the result.
718 FunctionLiteral* result = NULL;
719
720 {
721 // Parse the function literal.
Steve Block44f0eee2011-05-26 01:26:41 +0100722 Handle<String> no_name = isolate()->factory()->empty_symbol();
723 Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
724 if (!info->closure().is_null()) {
725 scope = Scope::DeserializeScopeChain(info, scope);
726 }
727 LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000728
Steve Block44f0eee2011-05-26 01:26:41 +0100729 if (shared_info->strict_mode()) {
730 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100731 }
732
Ben Murdochf87a2032010-10-22 12:50:53 +0100733 FunctionLiteralType type =
Steve Block44f0eee2011-05-26 01:26:41 +0100734 shared_info->is_expression() ? EXPRESSION : DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000735 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100736 result = ParseFunctionLiteral(name,
737 false, // Strict mode name already checked.
738 RelocInfo::kNoPosition, type, &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000739 // Make sure the results agree.
740 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000741 }
742
743 // Make sure the target stack is empty.
744 ASSERT(target_stack_ == NULL);
745
746 // If there was a stack overflow we have to get rid of AST and it is
747 // not safe to do before scope has been deleted.
748 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100749 zone_scope->DeleteOnExit();
Steve Block44f0eee2011-05-26 01:26:41 +0100750 if (stack_overflow_) isolate()->StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100751 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100752 Handle<String> inferred_name(shared_info->inferred_name());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100753 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000754 }
755 return result;
756}
757
Ben Murdochf87a2032010-10-22 12:50:53 +0100758
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800759Handle<String> Parser::GetSymbol(bool* ok) {
760 int symbol_id = -1;
761 if (pre_data() != NULL) {
762 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000763 }
Steve Block9fac8402011-05-12 15:51:54 +0100764 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000765}
Steve Blocka7e24c12009-10-30 11:49:00 +0000766
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800767
Steve Blocka7e24c12009-10-30 11:49:00 +0000768void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100769 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000770 ReportMessageAt(source_location, type, args);
771}
772
773
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800774void Parser::ReportMessageAt(Scanner::Location source_location,
775 const char* type,
776 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000777 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100778 source_location.beg_pos,
779 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100780 Factory* factory = isolate()->factory();
781 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000782 for (int i = 0; i < args.length(); i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100783 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100784 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000785 }
Steve Block44f0eee2011-05-26 01:26:41 +0100786 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
787 Handle<Object> result = factory->NewSyntaxError(type, array);
788 isolate()->Throw(*result, &location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000789}
790
791
Ben Murdochb8e0da22011-05-16 14:20:40 +0100792void Parser::ReportMessageAt(Scanner::Location source_location,
793 const char* type,
794 Vector<Handle<String> > args) {
795 MessageLocation location(script_,
796 source_location.beg_pos,
797 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100798 Factory* factory = isolate()->factory();
799 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100800 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100801 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100802 }
Steve Block44f0eee2011-05-26 01:26:41 +0100803 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
804 Handle<Object> result = factory->NewSyntaxError(type, array);
805 isolate()->Throw(*result, &location);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100806}
807
808
Steve Blocka7e24c12009-10-30 11:49:00 +0000809// Base class containing common code for the different finder classes used by
810// the parser.
811class ParserFinder {
812 protected:
813 ParserFinder() {}
814 static Assignment* AsAssignment(Statement* stat) {
815 if (stat == NULL) return NULL;
816 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
817 if (exp_stat == NULL) return NULL;
818 return exp_stat->expression()->AsAssignment();
819 }
820};
821
822
823// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000824// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000825class InitializationBlockFinder : public ParserFinder {
826 public:
827 InitializationBlockFinder()
828 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
829
830 ~InitializationBlockFinder() {
831 if (InBlock()) EndBlock();
832 }
833
834 void Update(Statement* stat) {
835 Assignment* assignment = AsAssignment(stat);
836 if (InBlock()) {
837 if (BlockContinues(assignment)) {
838 UpdateBlock(assignment);
839 } else {
840 EndBlock();
841 }
842 }
843 if (!InBlock() && (assignment != NULL) &&
844 (assignment->op() == Token::ASSIGN)) {
845 StartBlock(assignment);
846 }
847 }
848
849 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800850 // The minimum number of contiguous assignment that will
851 // be treated as an initialization block. Benchmarks show that
852 // the overhead exceeds the savings below this limit.
853 static const int kMinInitializationBlock = 3;
854
Steve Blocka7e24c12009-10-30 11:49:00 +0000855 // Returns true if the expressions appear to denote the same object.
856 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000857 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000858 static bool SameObject(Expression* e1, Expression* e2) {
859 VariableProxy* v1 = e1->AsVariableProxy();
860 VariableProxy* v2 = e2->AsVariableProxy();
861 if (v1 != NULL && v2 != NULL) {
862 return v1->name()->Equals(*v2->name());
863 }
864 Property* p1 = e1->AsProperty();
865 Property* p2 = e2->AsProperty();
866 if ((p1 == NULL) || (p2 == NULL)) return false;
867 Literal* key1 = p1->key()->AsLiteral();
868 Literal* key2 = p2->key()->AsLiteral();
869 if ((key1 == NULL) || (key2 == NULL)) return false;
870 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
871 return false;
872 }
873 String* name1 = String::cast(*key1->handle());
874 String* name2 = String::cast(*key2->handle());
875 if (!name1->Equals(name2)) return false;
876 return SameObject(p1->obj(), p2->obj());
877 }
878
879 // Returns true if the expressions appear to denote different properties
880 // of the same object.
881 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
882 Property* p1 = e1->AsProperty();
883 Property* p2 = e2->AsProperty();
884 if ((p1 == NULL) || (p2 == NULL)) return false;
885 return SameObject(p1->obj(), p2->obj());
886 }
887
888 bool BlockContinues(Assignment* assignment) {
889 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
890 if (assignment->op() != Token::ASSIGN) return false;
891 return PropertyOfSameObject(first_in_block_->target(),
892 assignment->target());
893 }
894
895 void StartBlock(Assignment* assignment) {
896 first_in_block_ = assignment;
897 last_in_block_ = assignment;
898 block_size_ = 1;
899 }
900
901 void UpdateBlock(Assignment* assignment) {
902 last_in_block_ = assignment;
903 ++block_size_;
904 }
905
906 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800907 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000908 first_in_block_->mark_block_start();
909 last_in_block_->mark_block_end();
910 }
911 last_in_block_ = first_in_block_ = NULL;
912 block_size_ = 0;
913 }
914
915 bool InBlock() { return first_in_block_ != NULL; }
916
917 Assignment* first_in_block_;
918 Assignment* last_in_block_;
919 int block_size_;
920
921 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
922};
923
924
925// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
926// this.x = ...;, where x is a named property. It also determines whether a
927// function contains only assignments of this type.
928class ThisNamedPropertyAssigmentFinder : public ParserFinder {
929 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100930 explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate)
931 : isolate_(isolate),
932 only_simple_this_property_assignments_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000933 names_(NULL),
934 assigned_arguments_(NULL),
935 assigned_constants_(NULL) {}
936
937 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000938 // Bail out if function already has property assignment that are
939 // not simple this property assignments.
940 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000941 return;
942 }
943
944 // Check whether this statement is of the form this.x = ...;
945 Assignment* assignment = AsAssignment(stat);
946 if (IsThisPropertyAssignment(assignment)) {
947 HandleThisPropertyAssignment(scope, assignment);
948 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000949 only_simple_this_property_assignments_ = false;
950 }
951 }
952
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 // Returns whether only statements of the form this.x = y; where y is either a
954 // constant or a function argument was encountered.
955 bool only_simple_this_property_assignments() {
956 return only_simple_this_property_assignments_;
957 }
958
959 // Returns a fixed array containing three elements for each assignment of the
960 // form this.x = y;
961 Handle<FixedArray> GetThisPropertyAssignments() {
962 if (names_ == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100963 return isolate_->factory()->empty_fixed_array();
Steve Blocka7e24c12009-10-30 11:49:00 +0000964 }
965 ASSERT(names_ != NULL);
966 ASSERT(assigned_arguments_ != NULL);
967 ASSERT_EQ(names_->length(), assigned_arguments_->length());
968 ASSERT_EQ(names_->length(), assigned_constants_->length());
969 Handle<FixedArray> assignments =
Steve Block44f0eee2011-05-26 01:26:41 +0100970 isolate_->factory()->NewFixedArray(names_->length() * 3);
Steve Blocka7e24c12009-10-30 11:49:00 +0000971 for (int i = 0; i < names_->length(); i++) {
972 assignments->set(i * 3, *names_->at(i));
973 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
974 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
975 }
976 return assignments;
977 }
978
979 private:
980 bool IsThisPropertyAssignment(Assignment* assignment) {
981 if (assignment != NULL) {
982 Property* property = assignment->target()->AsProperty();
983 return assignment->op() == Token::ASSIGN
984 && property != NULL
985 && property->obj()->AsVariableProxy() != NULL
986 && property->obj()->AsVariableProxy()->is_this();
987 }
988 return false;
989 }
990
991 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +0100992 // Check that the property assigned to is a named property, which is not
993 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +0000994 Property* property = assignment->target()->AsProperty();
995 ASSERT(property != NULL);
996 Literal* literal = property->key()->AsLiteral();
997 uint32_t dummy;
998 if (literal != NULL &&
999 literal->handle()->IsString() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001000 !String::cast(*(literal->handle()))->Equals(
1001 isolate_->heap()->Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1003 Handle<String> key = Handle<String>::cast(literal->handle());
1004
1005 // Check whether the value assigned is either a constant or matches the
1006 // name of one of the arguments to the function.
1007 if (assignment->value()->AsLiteral() != NULL) {
1008 // Constant assigned.
1009 Literal* literal = assignment->value()->AsLiteral();
1010 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001011 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001012 } else if (assignment->value()->AsVariableProxy() != NULL) {
1013 // Variable assigned.
1014 Handle<String> name =
1015 assignment->value()->AsVariableProxy()->name();
1016 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001017 for (int i = 0; i < scope->num_parameters(); i++) {
1018 if (*scope->parameter(i)->name() == *name) {
1019 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001020 AssignmentFromParameter(key, i);
1021 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001022 }
1023 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001024 }
1025 }
Steve Blockd0582a62009-12-15 09:54:21 +00001026 // It is not a simple "this.x = value;" assignment with a constant
1027 // or parameter value.
1028 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 }
1030
1031 void AssignmentFromParameter(Handle<String> name, int index) {
1032 EnsureAllocation();
1033 names_->Add(name);
1034 assigned_arguments_->Add(index);
Steve Block44f0eee2011-05-26 01:26:41 +01001035 assigned_constants_->Add(isolate_->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 }
1037
1038 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
1039 EnsureAllocation();
1040 names_->Add(name);
1041 assigned_arguments_->Add(-1);
1042 assigned_constants_->Add(value);
1043 }
1044
Steve Blockd0582a62009-12-15 09:54:21 +00001045 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 // The this assignment is not a simple one.
1047 only_simple_this_property_assignments_ = false;
1048 }
1049
1050 void EnsureAllocation() {
1051 if (names_ == NULL) {
1052 ASSERT(assigned_arguments_ == NULL);
1053 ASSERT(assigned_constants_ == NULL);
1054 names_ = new ZoneStringList(4);
1055 assigned_arguments_ = new ZoneList<int>(4);
1056 assigned_constants_ = new ZoneObjectList(4);
1057 }
1058 }
1059
Steve Block44f0eee2011-05-26 01:26:41 +01001060 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001061 bool only_simple_this_property_assignments_;
1062 ZoneStringList* names_;
1063 ZoneList<int>* assigned_arguments_;
1064 ZoneObjectList* assigned_constants_;
1065};
1066
1067
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001068void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001069 int end_token,
1070 bool* ok) {
1071 // SourceElements ::
1072 // (Statement)* <end_token>
1073
1074 // Allocate a target stack to use for this set of source
1075 // elements. This way, all scripts and functions get their own
1076 // target stack thus avoiding illegal breaks and continues across
1077 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001078 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001079
1080 ASSERT(processor != NULL);
1081 InitializationBlockFinder block_finder;
Steve Block44f0eee2011-05-26 01:26:41 +01001082 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
Steve Block1e0659c2011-05-24 12:43:12 +01001083 bool directive_prologue = true; // Parsing directive prologue.
1084
Steve Blocka7e24c12009-10-30 11:49:00 +00001085 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001086 if (directive_prologue && peek() != Token::STRING) {
1087 directive_prologue = false;
1088 }
1089
1090 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001091
1092 Statement* stat;
1093 if (peek() == Token::FUNCTION) {
1094 // FunctionDeclaration is only allowed in the context of SourceElements
1095 // (Ecma 262 5th Edition, clause 14):
1096 // SourceElement:
1097 // Statement
1098 // FunctionDeclaration
1099 // Common language extension is to allow function declaration in place
1100 // of any statement. This language extension is disabled in strict mode.
1101 stat = ParseFunctionDeclaration(CHECK_OK);
1102 } else {
1103 stat = ParseStatement(NULL, CHECK_OK);
1104 }
Steve Block1e0659c2011-05-24 12:43:12 +01001105
1106 if (stat == NULL || stat->IsEmpty()) {
1107 directive_prologue = false; // End of directive prologue.
1108 continue;
1109 }
1110
1111 if (directive_prologue) {
1112 // A shot at a directive.
1113 ExpressionStatement *e_stat;
1114 Literal *literal;
1115 // Still processing directive prologue?
1116 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1117 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1118 literal->handle()->IsString()) {
1119 Handle<String> directive = Handle<String>::cast(literal->handle());
1120
1121 // Check "use strict" directive (ES5 14.1).
Steve Block44f0eee2011-05-26 01:26:41 +01001122 if (!top_scope_->is_strict_mode() &&
1123 directive->Equals(isolate()->heap()->use_strict()) &&
Steve Block1e0659c2011-05-24 12:43:12 +01001124 token_loc.end_pos - token_loc.beg_pos ==
Steve Block44f0eee2011-05-26 01:26:41 +01001125 isolate()->heap()->use_strict()->length() + 2) {
1126 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +01001127 // "use strict" is the only directive for now.
1128 directive_prologue = false;
1129 }
1130 } else {
1131 // End of the directive prologue.
1132 directive_prologue = false;
1133 }
1134 }
1135
Steve Blocka7e24c12009-10-30 11:49:00 +00001136 // We find and mark the initialization blocks on top level code only.
1137 // This is because the optimization prevents reuse of the map transitions,
1138 // so it should be used only for code that will only be run once.
1139 if (top_scope_->is_global_scope()) {
1140 block_finder.Update(stat);
1141 }
1142 // Find and mark all assignments to named properties in this (this.x =)
1143 if (top_scope_->is_function_scope()) {
1144 this_property_assignment_finder.Update(top_scope_, stat);
1145 }
1146 processor->Add(stat);
1147 }
1148
1149 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001150 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001151 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001152 this_property_assignment_finder.only_simple_this_property_assignments()
1153 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001154 if (only_simple_this_property_assignments) {
Steve Block44f0eee2011-05-26 01:26:41 +01001155 lexical_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001156 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001157 this_property_assignment_finder.GetThisPropertyAssignments());
1158 }
1159 }
1160 return 0;
1161}
1162
1163
1164Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1165 // Statement ::
1166 // Block
1167 // VariableStatement
1168 // EmptyStatement
1169 // ExpressionStatement
1170 // IfStatement
1171 // IterationStatement
1172 // ContinueStatement
1173 // BreakStatement
1174 // ReturnStatement
1175 // WithStatement
1176 // LabelledStatement
1177 // SwitchStatement
1178 // ThrowStatement
1179 // TryStatement
1180 // DebuggerStatement
1181
1182 // Note: Since labels can only be used by 'break' and 'continue'
1183 // statements, which themselves are only valid within blocks,
1184 // iterations or 'switch' statements (i.e., BreakableStatements),
1185 // labels can be simply ignored in all other cases; except for
1186 // trivial labeled break statements 'label: break label' which is
1187 // parsed into an empty statement.
1188
1189 // Keep the source position of the statement
1190 int statement_pos = scanner().peek_location().beg_pos;
1191 Statement* stmt = NULL;
1192 switch (peek()) {
1193 case Token::LBRACE:
1194 return ParseBlock(labels, ok);
1195
1196 case Token::CONST: // fall through
1197 case Token::VAR:
1198 stmt = ParseVariableStatement(ok);
1199 break;
1200
1201 case Token::SEMICOLON:
1202 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001203 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001204
1205 case Token::IF:
1206 stmt = ParseIfStatement(labels, ok);
1207 break;
1208
1209 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001210 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001211 break;
1212
1213 case Token::WHILE:
1214 stmt = ParseWhileStatement(labels, ok);
1215 break;
1216
1217 case Token::FOR:
1218 stmt = ParseForStatement(labels, ok);
1219 break;
1220
1221 case Token::CONTINUE:
1222 stmt = ParseContinueStatement(ok);
1223 break;
1224
1225 case Token::BREAK:
1226 stmt = ParseBreakStatement(labels, ok);
1227 break;
1228
1229 case Token::RETURN:
1230 stmt = ParseReturnStatement(ok);
1231 break;
1232
1233 case Token::WITH:
1234 stmt = ParseWithStatement(labels, ok);
1235 break;
1236
1237 case Token::SWITCH:
1238 stmt = ParseSwitchStatement(labels, ok);
1239 break;
1240
1241 case Token::THROW:
1242 stmt = ParseThrowStatement(ok);
1243 break;
1244
1245 case Token::TRY: {
1246 // NOTE: It is somewhat complicated to have labels on
1247 // try-statements. When breaking out of a try-finally statement,
1248 // one must take great care not to treat it as a
1249 // fall-through. It is much easier just to wrap the entire
1250 // try-statement in a statement block and put the labels there
Ben Murdoch8b112d22011-06-08 16:22:53 +01001251 Block* result = new(zone()) Block(labels, 1, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001252 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001253 TryStatement* statement = ParseTryStatement(CHECK_OK);
1254 if (statement) {
1255 statement->set_statement_pos(statement_pos);
1256 }
1257 if (result) result->AddStatement(statement);
1258 return result;
1259 }
1260
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001261 case Token::FUNCTION: {
1262 // In strict mode, FunctionDeclaration is only allowed in the context
1263 // of SourceElements.
Steve Block44f0eee2011-05-26 01:26:41 +01001264 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001265 ReportMessageAt(scanner().peek_location(), "strict_function",
1266 Vector<const char*>::empty());
1267 *ok = false;
1268 return NULL;
1269 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001270 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001271 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001272
1273 case Token::NATIVE:
1274 return ParseNativeDeclaration(ok);
1275
1276 case Token::DEBUGGER:
1277 stmt = ParseDebuggerStatement(ok);
1278 break;
1279
1280 default:
1281 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1282 }
1283
1284 // Store the source position of the statement
1285 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1286 return stmt;
1287}
1288
1289
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001290VariableProxy* Parser::Declare(Handle<String> name,
1291 Variable::Mode mode,
1292 FunctionLiteral* fun,
1293 bool resolve,
1294 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001295 Variable* var = NULL;
1296 // If we are inside a function, a declaration of a variable
1297 // is a truly local variable, and the scope of the variable
1298 // is always the function scope.
1299
1300 // If a function scope exists, then we can statically declare this
1301 // variable and also set its mode. In any case, a Declaration node
1302 // will be added to the scope so that the declaration can be added
1303 // to the corresponding activation frame at runtime if necessary.
1304 // For instance declarations inside an eval scope need to be added
1305 // to the calling function context.
1306 if (top_scope_->is_function_scope()) {
1307 // Declare the variable in the function scope.
1308 var = top_scope_->LocalLookup(name);
1309 if (var == NULL) {
1310 // Declare the name.
1311 var = top_scope_->DeclareLocal(name, mode);
1312 } else {
1313 // The name was declared before; check for conflicting
1314 // re-declarations. If the previous declaration was a const or the
1315 // current declaration is a const then we have a conflict. There is
1316 // similar code in runtime.cc in the Declare functions.
1317 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1318 // We only have vars and consts in declarations.
1319 ASSERT(var->mode() == Variable::VAR ||
1320 var->mode() == Variable::CONST);
1321 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1322 Handle<String> type_string =
Steve Block44f0eee2011-05-26 01:26:41 +01001323 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001324 Expression* expression =
Steve Block44f0eee2011-05-26 01:26:41 +01001325 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00001326 type_string, name);
1327 top_scope_->SetIllegalRedeclaration(expression);
1328 }
1329 }
1330 }
1331
1332 // We add a declaration node for every declaration. The compiler
1333 // will only generate code if necessary. In particular, declarations
1334 // for inner local variables that do not represent functions won't
1335 // result in any generated code.
1336 //
1337 // Note that we always add an unresolved proxy even if it's not
1338 // used, simply because we don't know in this method (w/o extra
1339 // parameters) if the proxy is needed or not. The proxy will be
1340 // bound during variable resolution time unless it was pre-bound
1341 // below.
1342 //
1343 // WARNING: This will lead to multiple declaration nodes for the
1344 // same variable if it is declared several times. This is not a
1345 // semantic issue as long as we keep the source order, but it may be
1346 // a performance issue since it may lead to repeated
1347 // Runtime::DeclareContextSlot() calls.
1348 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001349 top_scope_->AddDeclaration(new(zone()) Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001350
1351 // For global const variables we bind the proxy to a variable.
1352 if (mode == Variable::CONST && top_scope_->is_global_scope()) {
1353 ASSERT(resolve); // should be set by all callers
1354 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001355 var = new(zone()) Variable(top_scope_, name, Variable::CONST, true, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001356 }
1357
1358 // If requested and we have a local variable, bind the proxy to the variable
1359 // at parse-time. This is used for functions (and consts) declared inside
1360 // statements: the corresponding function (or const) variable must be in the
1361 // function scope and not a statement-local scope, e.g. as provided with a
1362 // 'with' statement:
1363 //
1364 // with (obj) {
1365 // function f() {}
1366 // }
1367 //
1368 // which is translated into:
1369 //
1370 // with (obj) {
1371 // // in this case this is not: 'var f; f = function () {};'
1372 // var f = function () {};
1373 // }
1374 //
1375 // Note that if 'f' is accessed from inside the 'with' statement, it
1376 // will be allocated in the context (because we must be able to look
1377 // it up dynamically) but it will also be accessed statically, i.e.,
1378 // with a context slot index and a context chain length for this
1379 // initialization code. Thus, inside the 'with' statement, we need
1380 // both access to the static and the dynamic context chain; the
1381 // runtime needs to provide both.
1382 if (resolve && var != NULL) proxy->BindTo(var);
1383
1384 return proxy;
1385}
1386
1387
1388// Language extension which is only enabled for source files loaded
1389// through the API's extension mechanism. A native function
1390// declaration is resolved by looking up the function through a
1391// callback provided by the extension.
1392Statement* Parser::ParseNativeDeclaration(bool* ok) {
1393 if (extension_ == NULL) {
1394 ReportUnexpectedToken(Token::NATIVE);
1395 *ok = false;
1396 return NULL;
1397 }
1398
1399 Expect(Token::NATIVE, CHECK_OK);
1400 Expect(Token::FUNCTION, CHECK_OK);
1401 Handle<String> name = ParseIdentifier(CHECK_OK);
1402 Expect(Token::LPAREN, CHECK_OK);
1403 bool done = (peek() == Token::RPAREN);
1404 while (!done) {
1405 ParseIdentifier(CHECK_OK);
1406 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001407 if (!done) {
1408 Expect(Token::COMMA, CHECK_OK);
1409 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 }
1411 Expect(Token::RPAREN, CHECK_OK);
1412 Expect(Token::SEMICOLON, CHECK_OK);
1413
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 // Make sure that the function containing the native declaration
1415 // isn't lazily compiled. The extension structures are only
1416 // accessible while parsing the first time not when reparsing
1417 // because of lazy compilation.
1418 top_scope_->ForceEagerCompilation();
1419
1420 // Compute the function template for the native function.
1421 v8::Handle<v8::FunctionTemplate> fun_template =
1422 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1423 ASSERT(!fun_template.IsEmpty());
1424
Steve Block6ded16b2010-05-10 14:33:55 +01001425 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001426 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1427 const int literals = fun->NumberOfLiterals();
1428 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001429 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001430 Handle<SharedFunctionInfo> shared =
Steve Block44f0eee2011-05-26 01:26:41 +01001431 isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001432 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001433 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001434
Steve Block6ded16b2010-05-10 14:33:55 +01001435 // Copy the function data to the shared function info.
1436 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001437 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001438 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001439
1440 // TODO(1240846): It's weird that native function declarations are
1441 // introduced dynamically when we meet their declarations, whereas
1442 // other functions are setup when entering the surrounding scope.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001443 SharedFunctionInfoLiteral* lit =
1444 new(zone()) SharedFunctionInfoLiteral(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001446 return new(zone()) ExpressionStatement(new(zone()) Assignment(
1447 Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001448}
1449
1450
1451Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1452 // FunctionDeclaration ::
1453 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1454 Expect(Token::FUNCTION, CHECK_OK);
1455 int function_token_position = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01001456 bool is_reserved = false;
1457 Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001458 FunctionLiteral* fun = ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01001459 is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001460 function_token_position,
1461 DECLARATION,
1462 CHECK_OK);
1463 // Even if we're not at the top-level of the global or a function
1464 // scope, we treat is as such and introduce the function with it's
1465 // initial value upon entering the corresponding scope.
1466 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001467 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001468}
1469
1470
1471Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1472 // Block ::
1473 // '{' Statement* '}'
1474
1475 // Note that a Block does not introduce a new execution scope!
1476 // (ECMA-262, 3rd, 12.2)
1477 //
1478 // Construct block expecting 16 statements.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001479 Block* result = new(zone()) Block(labels, 16, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001480 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 Expect(Token::LBRACE, CHECK_OK);
1482 while (peek() != Token::RBRACE) {
1483 Statement* stat = ParseStatement(NULL, CHECK_OK);
1484 if (stat && !stat->IsEmpty()) result->AddStatement(stat);
1485 }
1486 Expect(Token::RBRACE, CHECK_OK);
1487 return result;
1488}
1489
1490
1491Block* Parser::ParseVariableStatement(bool* ok) {
1492 // VariableStatement ::
1493 // VariableDeclarations ';'
1494
1495 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature
1496 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK);
1497 ExpectSemicolon(CHECK_OK);
1498 return result;
1499}
1500
Steve Block44f0eee2011-05-26 01:26:41 +01001501
1502bool Parser::IsEvalOrArguments(Handle<String> string) {
1503 return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
1504 string.is_identical_to(isolate()->factory()->arguments_symbol());
Steve Block1e0659c2011-05-24 12:43:12 +01001505}
Steve Blocka7e24c12009-10-30 11:49:00 +00001506
Steve Block44f0eee2011-05-26 01:26:41 +01001507
Steve Blocka7e24c12009-10-30 11:49:00 +00001508// If the variable declaration declares exactly one non-const
1509// variable, then *var is set to that variable. In all other cases,
1510// *var is untouched; in particular, it is the caller's responsibility
1511// to initialize it properly. This mechanism is used for the parsing
1512// of 'for-in' loops.
1513Block* Parser::ParseVariableDeclarations(bool accept_IN,
1514 Expression** var,
1515 bool* ok) {
1516 // VariableDeclarations ::
1517 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1518
1519 Variable::Mode mode = Variable::VAR;
1520 bool is_const = false;
1521 if (peek() == Token::VAR) {
1522 Consume(Token::VAR);
1523 } else if (peek() == Token::CONST) {
1524 Consume(Token::CONST);
Steve Block44f0eee2011-05-26 01:26:41 +01001525 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001526 ReportMessage("strict_const", Vector<const char*>::empty());
1527 *ok = false;
1528 return NULL;
1529 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001530 mode = Variable::CONST;
1531 is_const = true;
1532 } else {
1533 UNREACHABLE(); // by current callers
1534 }
1535
1536 // The scope of a variable/const declared anywhere inside a function
1537 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1538 // transform a source-level variable/const declaration into a (Function)
1539 // Scope declaration, and rewrite the source-level initialization into an
1540 // assignment statement. We use a block to collect multiple assignments.
1541 //
1542 // We mark the block as initializer block because we don't want the
1543 // rewriter to add a '.result' assignment to such a block (to get compliant
1544 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1545 // reasons when pretty-printing. Also, unless an assignment (initialization)
1546 // is inside an initializer block, it is ignored.
1547 //
1548 // Create new block with one expected declaration.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001549 Block* block = new(zone()) Block(NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001550 VariableProxy* last_var = NULL; // the last variable declared
1551 int nvars = 0; // the number of variables declared
1552 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001553 if (fni_ != NULL) fni_->Enter();
1554
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 // Parse variable name.
1556 if (nvars > 0) Consume(Token::COMMA);
1557 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001558 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001559
Steve Block1e0659c2011-05-24 12:43:12 +01001560 // Strict mode variables may not be named eval or arguments
Steve Block44f0eee2011-05-26 01:26:41 +01001561 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01001562 ReportMessage("strict_var_name", Vector<const char*>::empty());
1563 *ok = false;
1564 return NULL;
1565 }
1566
Steve Blocka7e24c12009-10-30 11:49:00 +00001567 // Declare variable.
1568 // Note that we *always* must treat the initial value via a separate init
1569 // assignment for variables and constants because the value must be assigned
1570 // when the variable is encountered in the source. But the variable/constant
1571 // is declared (and set to 'undefined') upon entering the function within
1572 // which the variable or constant is declared. Only function variables have
1573 // an initial value in the declaration (because they are initialized upon
1574 // entering the function).
1575 //
1576 // If we have a const declaration, in an inner scope, the proxy is always
1577 // bound to the declared variable (independent of possibly surrounding with
1578 // statements).
1579 last_var = Declare(name, mode, NULL,
1580 is_const /* always bound for CONST! */,
1581 CHECK_OK);
1582 nvars++;
1583
1584 // Parse initialization expression if present and/or needed. A
1585 // declaration of the form:
1586 //
1587 // var v = x;
1588 //
1589 // is syntactic sugar for:
1590 //
1591 // var v; v = x;
1592 //
1593 // In particular, we need to re-lookup 'v' as it may be a
1594 // different 'v' than the 'v' in the declaration (if we are inside
1595 // a 'with' statement that makes a object property with name 'v'
1596 // visible).
1597 //
1598 // However, note that const declarations are different! A const
1599 // declaration of the form:
1600 //
1601 // const c = x;
1602 //
1603 // is *not* syntactic sugar for:
1604 //
1605 // const c; c = x;
1606 //
1607 // The "variable" c initialized to x is the same as the declared
1608 // one - there is no re-lookup (see the last parameter of the
1609 // Declare() call above).
1610
1611 Expression* value = NULL;
1612 int position = -1;
1613 if (peek() == Token::ASSIGN) {
1614 Expect(Token::ASSIGN, CHECK_OK);
1615 position = scanner().location().beg_pos;
1616 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001617 // Don't infer if it is "a = function(){...}();"-like expression.
1618 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer();
Steve Blocka7e24c12009-10-30 11:49:00 +00001619 }
1620
1621 // Make sure that 'const c' actually initializes 'c' to undefined
1622 // even though it seems like a stupid thing to do.
1623 if (value == NULL && is_const) {
1624 value = GetLiteralUndefined();
1625 }
1626
1627 // Global variable declarations must be compiled in a specific
1628 // way. When the script containing the global variable declaration
1629 // is entered, the global variable must be declared, so that if it
1630 // doesn't exist (not even in a prototype of the global object) it
1631 // gets created with an initial undefined value. This is handled
1632 // by the declarations part of the function representing the
1633 // top-level global code; see Runtime::DeclareGlobalVariable. If
1634 // it already exists (in the object or in a prototype), it is
1635 // *not* touched until the variable declaration statement is
1636 // executed.
1637 //
1638 // Executing the variable declaration statement will always
1639 // guarantee to give the global object a "local" variable; a
1640 // variable defined in the global object and not in any
1641 // prototype. This way, global variable declarations can shadow
1642 // properties in the prototype chain, but only after the variable
1643 // declaration statement has been executed. This is important in
1644 // browsers where the global object (window) has lots of
1645 // properties defined in prototype objects.
1646
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001647 if (top_scope_->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001648 // Compute the arguments for the runtime call.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001649 ZoneList<Expression*>* arguments = new ZoneList<Expression*>(3);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001650 // We have at least 1 parameter.
1651 arguments->Add(new(zone()) Literal(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001652 CallRuntime* initialize;
1653
1654 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001655 arguments->Add(value);
1656 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001657
1658 // Construct the call to Runtime_InitializeConstGlobal
1659 // and add it to the initialization statement block.
1660 // Note that the function does different things depending on
1661 // the number of arguments (1 or 2).
Steve Blocka7e24c12009-10-30 11:49:00 +00001662 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001663 new(zone()) CallRuntime(
Steve Block44f0eee2011-05-26 01:26:41 +01001664 isolate()->factory()->InitializeConstGlobal_symbol(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001665 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1666 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001667 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001668 // Add strict mode.
1669 // We may want to pass singleton to avoid Literal allocations.
1670 arguments->Add(NewNumberLiteral(
Steve Block44f0eee2011-05-26 01:26:41 +01001671 top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001672
1673 // Be careful not to assign a value to the global variable if
1674 // we're in a with. The initialization value should not
1675 // necessarily be stored in the global object in that case,
1676 // which is why we need to generate a separate assignment node.
1677 if (value != NULL && !inside_with()) {
1678 arguments->Add(value);
1679 value = NULL; // zap the value to avoid the unnecessary assignment
1680 }
1681
1682 // Construct the call to Runtime_InitializeVarGlobal
1683 // and add it to the initialization statement block.
1684 // Note that the function does different things depending on
1685 // the number of arguments (2 or 3).
Steve Blocka7e24c12009-10-30 11:49:00 +00001686 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001687 new(zone()) CallRuntime(
Steve Block44f0eee2011-05-26 01:26:41 +01001688 isolate()->factory()->InitializeVarGlobal_symbol(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001689 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1690 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001691 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001692
Ben Murdoch8b112d22011-06-08 16:22:53 +01001693 block->AddStatement(new(zone()) ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001694 }
1695
1696 // Add an assignment node to the initialization statement block if
1697 // we still have a pending initialization value. We must distinguish
1698 // between variables and constants: Variable initializations are simply
1699 // assignments (with all the consequences if they are inside a 'with'
1700 // statement - they may change a 'with' object property). Constant
1701 // initializations always assign to the declared constant which is
1702 // always at the function scope level. This is only relevant for
1703 // dynamically looked-up variables and constants (the start context
1704 // for constant lookups is always the function context, while it is
1705 // the top context for variables). Sigh...
1706 if (value != NULL) {
1707 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001708 Assignment* assignment =
1709 new(zone()) Assignment(op, last_var, value, position);
1710 if (block) {
1711 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1712 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001713 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001714
1715 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001716 } while (peek() == Token::COMMA);
1717
1718 if (!is_const && nvars == 1) {
1719 // We have a single, non-const variable.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001720 ASSERT(last_var != NULL);
1721 *var = last_var;
Steve Blocka7e24c12009-10-30 11:49:00 +00001722 }
1723
1724 return block;
1725}
1726
1727
1728static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1729 ASSERT(!label.is_null());
1730 if (labels != NULL)
1731 for (int i = labels->length(); i-- > 0; )
1732 if (labels->at(i).is_identical_to(label))
1733 return true;
1734
1735 return false;
1736}
1737
1738
1739Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1740 bool* ok) {
1741 // ExpressionStatement | LabelledStatement ::
1742 // Expression ';'
1743 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001744 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001745 Expression* expr = ParseExpression(true, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001746 if (peek() == Token::COLON && starts_with_idenfifier && expr &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001747 expr->AsVariableProxy() != NULL &&
1748 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001749 // Expression is a single identifier, and not, e.g., a parenthesized
1750 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001751 VariableProxy* var = expr->AsVariableProxy();
1752 Handle<String> label = var->name();
1753 // TODO(1240780): We don't check for redeclaration of labels
1754 // during preparsing since keeping track of the set of active
1755 // labels requires nontrivial changes to the way scopes are
1756 // structured. However, these are probably changes we want to
1757 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001758 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1759 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1760 const char* elms[2] = { "Label", *c_string };
1761 Vector<const char*> args(elms, 2);
1762 ReportMessage("redeclaration", args);
1763 *ok = false;
1764 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001765 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001766 if (labels == NULL) labels = new ZoneStringList(4);
1767 labels->Add(label);
1768 // Remove the "ghost" variable that turned out to be a label
1769 // from the top scope. This way, we don't try to resolve it
1770 // during the scope processing.
1771 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001772 Expect(Token::COLON, CHECK_OK);
1773 return ParseStatement(labels, ok);
1774 }
1775
1776 // Parsed expression statement.
1777 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001778 return new(zone()) ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001779}
1780
1781
1782IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1783 // IfStatement ::
1784 // 'if' '(' Expression ')' Statement ('else' Statement)?
1785
1786 Expect(Token::IF, CHECK_OK);
1787 Expect(Token::LPAREN, CHECK_OK);
1788 Expression* condition = ParseExpression(true, CHECK_OK);
1789 Expect(Token::RPAREN, CHECK_OK);
1790 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1791 Statement* else_statement = NULL;
1792 if (peek() == Token::ELSE) {
1793 Next();
1794 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001795 } else {
1796 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001797 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01001798 return new(zone()) IfStatement(condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001799}
1800
1801
1802Statement* Parser::ParseContinueStatement(bool* ok) {
1803 // ContinueStatement ::
1804 // 'continue' Identifier? ';'
1805
1806 Expect(Token::CONTINUE, CHECK_OK);
1807 Handle<String> label = Handle<String>::null();
1808 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001809 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001810 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1811 label = ParseIdentifier(CHECK_OK);
1812 }
1813 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001814 target = LookupContinueTarget(label, CHECK_OK);
1815 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001816 // Illegal continue statement.
1817 const char* message = "illegal_continue";
1818 Vector<Handle<String> > args;
1819 if (!label.is_null()) {
1820 message = "unknown_label";
1821 args = Vector<Handle<String> >(&label, 1);
1822 }
1823 ReportMessageAt(scanner().location(), message, args);
1824 *ok = false;
1825 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001826 }
1827 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001828 return new(zone()) ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001829}
1830
1831
1832Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1833 // BreakStatement ::
1834 // 'break' Identifier? ';'
1835
1836 Expect(Token::BREAK, CHECK_OK);
1837 Handle<String> label;
1838 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001839 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001840 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1841 label = ParseIdentifier(CHECK_OK);
1842 }
1843 // Parse labeled break statements that target themselves into
1844 // empty statements, e.g. 'l1: l2: l3: break l2;'
1845 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001846 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001847 }
1848 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001849 target = LookupBreakTarget(label, CHECK_OK);
1850 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001851 // Illegal break statement.
1852 const char* message = "illegal_break";
1853 Vector<Handle<String> > args;
1854 if (!label.is_null()) {
1855 message = "unknown_label";
1856 args = Vector<Handle<String> >(&label, 1);
1857 }
1858 ReportMessageAt(scanner().location(), message, args);
1859 *ok = false;
1860 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001861 }
1862 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001863 return new(zone()) BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001864}
1865
1866
1867Statement* Parser::ParseReturnStatement(bool* ok) {
1868 // ReturnStatement ::
1869 // 'return' Expression? ';'
1870
1871 // Consume the return token. It is necessary to do the before
1872 // reporting any errors on it, because of the way errors are
1873 // reported (underlining).
1874 Expect(Token::RETURN, CHECK_OK);
1875
1876 // An ECMAScript program is considered syntactically incorrect if it
1877 // contains a return statement that is not within the body of a
1878 // function. See ECMA-262, section 12.9, page 67.
1879 //
1880 // To be consistent with KJS we report the syntax error at runtime.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001881 if (!top_scope_->is_function_scope()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001882 Handle<String> type = isolate()->factory()->illegal_return_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00001883 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001884 return new(zone()) ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001885 }
1886
1887 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001888 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001889 tok == Token::SEMICOLON ||
1890 tok == Token::RBRACE ||
1891 tok == Token::EOS) {
1892 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001893 return new(zone()) ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001894 }
1895
1896 Expression* expr = ParseExpression(true, CHECK_OK);
1897 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001898 return new(zone()) ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001899}
1900
1901
1902Block* Parser::WithHelper(Expression* obj,
1903 ZoneStringList* labels,
1904 bool is_catch_block,
1905 bool* ok) {
1906 // Parse the statement and collect escaping labels.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001907 ZoneList<Label*>* target_list = new ZoneList<Label*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001908 TargetCollector collector(target_list);
1909 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001910 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001911 with_nesting_level_++;
1912 top_scope_->RecordWithStatement();
1913 stat = ParseStatement(labels, CHECK_OK);
1914 with_nesting_level_--;
1915 }
1916 // Create resulting block with two statements.
1917 // 1: Evaluate the with expression.
1918 // 2: The try-finally block evaluating the body.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001919 Block* result = new(zone()) Block(NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001920
1921 if (result != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001922 result->AddStatement(new(zone()) WithEnterStatement(obj, is_catch_block));
Steve Blocka7e24c12009-10-30 11:49:00 +00001923
1924 // Create body block.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001925 Block* body = new(zone()) Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001926 body->AddStatement(stat);
1927
1928 // Create exit block.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001929 Block* exit = new(zone()) Block(NULL, 1, false);
1930 exit->AddStatement(new(zone()) WithExitStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00001931
1932 // Return a try-finally statement.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001933 TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001934 wrapper->set_escaping_targets(collector.targets());
1935 result->AddStatement(wrapper);
1936 }
1937 return result;
1938}
1939
1940
1941Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
1942 // WithStatement ::
1943 // 'with' '(' Expression ')' Statement
1944
1945 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001946
Steve Block44f0eee2011-05-26 01:26:41 +01001947 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001948 ReportMessage("strict_mode_with", Vector<const char*>::empty());
1949 *ok = false;
1950 return NULL;
1951 }
1952
Steve Blocka7e24c12009-10-30 11:49:00 +00001953 Expect(Token::LPAREN, CHECK_OK);
1954 Expression* expr = ParseExpression(true, CHECK_OK);
1955 Expect(Token::RPAREN, CHECK_OK);
1956
1957 return WithHelper(expr, labels, false, CHECK_OK);
1958}
1959
1960
1961CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1962 // CaseClause ::
1963 // 'case' Expression ':' Statement*
1964 // 'default' ':' Statement*
1965
1966 Expression* label = NULL; // NULL expression indicates default case
1967 if (peek() == Token::CASE) {
1968 Expect(Token::CASE, CHECK_OK);
1969 label = ParseExpression(true, CHECK_OK);
1970 } else {
1971 Expect(Token::DEFAULT, CHECK_OK);
1972 if (*default_seen_ptr) {
1973 ReportMessage("multiple_defaults_in_switch",
1974 Vector<const char*>::empty());
1975 *ok = false;
1976 return NULL;
1977 }
1978 *default_seen_ptr = true;
1979 }
1980 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001981 int pos = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001982 ZoneList<Statement*>* statements = new ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001983 while (peek() != Token::CASE &&
1984 peek() != Token::DEFAULT &&
1985 peek() != Token::RBRACE) {
1986 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001987 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001988 }
1989
Ben Murdoch8b112d22011-06-08 16:22:53 +01001990 return new(zone()) CaseClause(label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001991}
1992
1993
1994SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
1995 bool* ok) {
1996 // SwitchStatement ::
1997 // 'switch' '(' Expression ')' '{' CaseClause* '}'
1998
Ben Murdoch8b112d22011-06-08 16:22:53 +01001999 SwitchStatement* statement = new(zone()) SwitchStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002000 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002001
2002 Expect(Token::SWITCH, CHECK_OK);
2003 Expect(Token::LPAREN, CHECK_OK);
2004 Expression* tag = ParseExpression(true, CHECK_OK);
2005 Expect(Token::RPAREN, CHECK_OK);
2006
2007 bool default_seen = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002008 ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002009 Expect(Token::LBRACE, CHECK_OK);
2010 while (peek() != Token::RBRACE) {
2011 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002012 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002013 }
2014 Expect(Token::RBRACE, CHECK_OK);
2015
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002016 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002017 return statement;
2018}
2019
2020
2021Statement* Parser::ParseThrowStatement(bool* ok) {
2022 // ThrowStatement ::
2023 // 'throw' Expression ';'
2024
2025 Expect(Token::THROW, CHECK_OK);
2026 int pos = scanner().location().beg_pos;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002027 if (scanner().has_line_terminator_before_next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002028 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2029 *ok = false;
2030 return NULL;
2031 }
2032 Expression* exception = ParseExpression(true, CHECK_OK);
2033 ExpectSemicolon(CHECK_OK);
2034
Ben Murdoch8b112d22011-06-08 16:22:53 +01002035 return new(zone()) ExpressionStatement(new(zone()) Throw(exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002036}
2037
2038
2039TryStatement* Parser::ParseTryStatement(bool* ok) {
2040 // TryStatement ::
2041 // 'try' Block Catch
2042 // 'try' Block Finally
2043 // 'try' Block Catch Finally
2044 //
2045 // Catch ::
2046 // 'catch' '(' Identifier ')' Block
2047 //
2048 // Finally ::
2049 // 'finally' Block
2050
2051 Expect(Token::TRY, CHECK_OK);
2052
Ben Murdoch8b112d22011-06-08 16:22:53 +01002053 ZoneList<Label*>* target_list = new ZoneList<Label*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002054 TargetCollector collector(target_list);
2055 Block* try_block;
2056
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002057 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002058 try_block = ParseBlock(NULL, CHECK_OK);
2059 }
2060
2061 Block* catch_block = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002062 Variable* catch_var = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002063 Block* finally_block = NULL;
2064
2065 Token::Value tok = peek();
2066 if (tok != Token::CATCH && tok != Token::FINALLY) {
2067 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2068 *ok = false;
2069 return NULL;
2070 }
2071
2072 // If we can break out from the catch block and there is a finally block,
2073 // then we will need to collect jump targets from the catch block. Since
2074 // we don't know yet if there will be a finally block, we always collect
2075 // the jump targets.
Ben Murdoch8b112d22011-06-08 16:22:53 +01002076 ZoneList<Label*>* catch_target_list = new ZoneList<Label*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002077 TargetCollector catch_collector(catch_target_list);
2078 bool has_catch = false;
2079 if (tok == Token::CATCH) {
2080 has_catch = true;
2081 Consume(Token::CATCH);
2082
2083 Expect(Token::LPAREN, CHECK_OK);
2084 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002085
Steve Block44f0eee2011-05-26 01:26:41 +01002086 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01002087 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2088 *ok = false;
2089 return NULL;
2090 }
2091
Steve Blocka7e24c12009-10-30 11:49:00 +00002092 Expect(Token::RPAREN, CHECK_OK);
2093
2094 if (peek() == Token::LBRACE) {
2095 // Allocate a temporary for holding the finally state while
2096 // executing the finally block.
Steve Block44f0eee2011-05-26 01:26:41 +01002097 catch_var =
2098 top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002099 Literal* name_literal = new(zone()) Literal(name);
2100 VariableProxy* catch_var_use = new(zone()) VariableProxy(catch_var);
2101 Expression* obj =
2102 new(zone()) CatchExtensionObject(name_literal, catch_var_use);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002103 { Target target(&this->target_stack_, &catch_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002104 catch_block = WithHelper(obj, NULL, true, CHECK_OK);
2105 }
2106 } else {
2107 Expect(Token::LBRACE, CHECK_OK);
2108 }
2109
2110 tok = peek();
2111 }
2112
2113 if (tok == Token::FINALLY || !has_catch) {
2114 Consume(Token::FINALLY);
2115 // Declare a variable for holding the finally state while
2116 // executing the finally block.
2117 finally_block = ParseBlock(NULL, CHECK_OK);
2118 }
2119
2120 // Simplify the AST nodes by converting:
2121 // 'try { } catch { } finally { }'
2122 // to:
2123 // 'try { try { } catch { } } finally { }'
2124
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002125 if (catch_block != NULL && finally_block != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002126 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
Steve Block3ce2e202009-11-05 08:53:23 +00002127 TryCatchStatement* statement =
Ben Murdoch8b112d22011-06-08 16:22:53 +01002128 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block);
Steve Blocka7e24c12009-10-30 11:49:00 +00002129 statement->set_escaping_targets(collector.targets());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002130 try_block = new(zone()) Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002131 try_block->AddStatement(statement);
2132 catch_block = NULL;
2133 }
2134
2135 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002136 if (catch_block != NULL) {
2137 ASSERT(finally_block == NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002138 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var);
2139 result =
2140 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002141 result->set_escaping_targets(collector.targets());
2142 } else {
2143 ASSERT(finally_block != NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002144 result = new(zone()) TryFinallyStatement(try_block, finally_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002145 // Add the jump targets of the try block and the catch block.
2146 for (int i = 0; i < collector.targets()->length(); i++) {
2147 catch_collector.AddTarget(collector.targets()->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002148 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002149 result->set_escaping_targets(catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002150 }
2151
2152 return result;
2153}
2154
2155
Steve Block3ce2e202009-11-05 08:53:23 +00002156DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2157 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002158 // DoStatement ::
2159 // 'do' Statement 'while' '(' Expression ')' ';'
2160
Ben Murdoch8b112d22011-06-08 16:22:53 +01002161 DoWhileStatement* loop = new(zone()) DoWhileStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002162 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002163
2164 Expect(Token::DO, CHECK_OK);
2165 Statement* body = ParseStatement(NULL, CHECK_OK);
2166 Expect(Token::WHILE, CHECK_OK);
2167 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002168
2169 if (loop != NULL) {
2170 int position = scanner().location().beg_pos;
2171 loop->set_condition_position(position);
2172 }
2173
Steve Blocka7e24c12009-10-30 11:49:00 +00002174 Expression* cond = ParseExpression(true, CHECK_OK);
2175 Expect(Token::RPAREN, CHECK_OK);
2176
2177 // Allow do-statements to be terminated with and without
2178 // semi-colons. This allows code such as 'do;while(0)return' to
2179 // parse, which would not be the case if we had used the
2180 // ExpectSemicolon() functionality here.
2181 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2182
Steve Block3ce2e202009-11-05 08:53:23 +00002183 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002184 return loop;
2185}
2186
2187
Steve Block3ce2e202009-11-05 08:53:23 +00002188WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002189 // WhileStatement ::
2190 // 'while' '(' Expression ')' Statement
2191
Ben Murdoch8b112d22011-06-08 16:22:53 +01002192 WhileStatement* loop = new(zone()) WhileStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002193 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002194
2195 Expect(Token::WHILE, CHECK_OK);
2196 Expect(Token::LPAREN, CHECK_OK);
2197 Expression* cond = ParseExpression(true, CHECK_OK);
2198 Expect(Token::RPAREN, CHECK_OK);
2199 Statement* body = ParseStatement(NULL, CHECK_OK);
2200
Steve Block3ce2e202009-11-05 08:53:23 +00002201 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002202 return loop;
2203}
2204
2205
2206Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2207 // ForStatement ::
2208 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2209
2210 Statement* init = NULL;
2211
2212 Expect(Token::FOR, CHECK_OK);
2213 Expect(Token::LPAREN, CHECK_OK);
2214 if (peek() != Token::SEMICOLON) {
2215 if (peek() == Token::VAR || peek() == Token::CONST) {
2216 Expression* each = NULL;
2217 Block* variable_statement =
2218 ParseVariableDeclarations(false, &each, CHECK_OK);
2219 if (peek() == Token::IN && each != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002220 ForInStatement* loop = new(zone()) ForInStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002221 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002222
2223 Expect(Token::IN, CHECK_OK);
2224 Expression* enumerable = ParseExpression(true, CHECK_OK);
2225 Expect(Token::RPAREN, CHECK_OK);
2226
2227 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002228 loop->Initialize(each, enumerable, body);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002229 Block* result = new(zone()) Block(NULL, 2, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002230 result->AddStatement(variable_statement);
2231 result->AddStatement(loop);
2232 // Parsed for-in loop w/ variable/const declaration.
2233 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002234 } else {
2235 init = variable_statement;
2236 }
2237
2238 } else {
2239 Expression* expression = ParseExpression(false, CHECK_OK);
2240 if (peek() == Token::IN) {
2241 // Signal a reference error if the expression is an invalid
2242 // left-hand side expression. We could report this as a syntax
2243 // error here but for compatibility with JSC we choose to report
2244 // the error at runtime.
2245 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002246 Handle<String> type =
2247 isolate()->factory()->invalid_lhs_in_for_in_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002248 expression = NewThrowReferenceError(type);
2249 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01002250 ForInStatement* loop = new(zone()) ForInStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002251 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002252
2253 Expect(Token::IN, CHECK_OK);
2254 Expression* enumerable = ParseExpression(true, CHECK_OK);
2255 Expect(Token::RPAREN, CHECK_OK);
2256
2257 Statement* body = ParseStatement(NULL, CHECK_OK);
2258 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002259 // Parsed for-in loop.
2260 return loop;
2261
2262 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002263 init = new(zone()) ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002264 }
2265 }
2266 }
2267
2268 // Standard 'for' loop
Ben Murdoch8b112d22011-06-08 16:22:53 +01002269 ForStatement* loop = new(zone()) ForStatement(labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002270 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002271
2272 // Parsed initializer at this point.
2273 Expect(Token::SEMICOLON, CHECK_OK);
2274
2275 Expression* cond = NULL;
2276 if (peek() != Token::SEMICOLON) {
2277 cond = ParseExpression(true, CHECK_OK);
2278 }
2279 Expect(Token::SEMICOLON, CHECK_OK);
2280
2281 Statement* next = NULL;
2282 if (peek() != Token::RPAREN) {
2283 Expression* exp = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002284 next = new(zone()) ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002285 }
2286 Expect(Token::RPAREN, CHECK_OK);
2287
2288 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002289 if (loop) loop->Initialize(init, cond, next, body);
2290 return loop;
2291}
2292
2293
2294// Precedence = 1
2295Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2296 // Expression ::
2297 // AssignmentExpression
2298 // Expression ',' AssignmentExpression
2299
2300 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2301 while (peek() == Token::COMMA) {
2302 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002303 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002304 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002305 result = new(zone()) BinaryOperation(Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002306 }
2307 return result;
2308}
2309
2310
2311// Precedence = 2
2312Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2313 // AssignmentExpression ::
2314 // ConditionalExpression
2315 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2316
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002317 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002318 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2319
2320 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002321 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002322 // Parsed conditional expression only (no assignment).
2323 return expression;
2324 }
2325
2326 // Signal a reference error if the expression is an invalid left-hand
2327 // side expression. We could report this as a syntax error here but
2328 // for compatibility with JSC we choose to report the error at
2329 // runtime.
2330 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002331 Handle<String> type =
2332 isolate()->factory()->invalid_lhs_in_assignment_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002333 expression = NewThrowReferenceError(type);
2334 }
2335
Steve Block44f0eee2011-05-26 01:26:41 +01002336 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002337 // Assignment to eval or arguments is disallowed in strict mode.
2338 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2339 }
2340
Steve Blocka7e24c12009-10-30 11:49:00 +00002341 Token::Value op = Next(); // Get assignment operator.
2342 int pos = scanner().location().beg_pos;
2343 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2344
2345 // TODO(1231235): We try to estimate the set of properties set by
2346 // constructors. We define a new property whenever there is an
2347 // assignment to a property of 'this'. We should probably only add
2348 // properties if we haven't seen them before. Otherwise we'll
2349 // probably overestimate the number of properties.
2350 Property* property = expression ? expression->AsProperty() : NULL;
2351 if (op == Token::ASSIGN &&
2352 property != NULL &&
2353 property->obj()->AsVariableProxy() != NULL &&
2354 property->obj()->AsVariableProxy()->is_this()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002355 lexical_scope_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002356 }
2357
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002358 // If we assign a function literal to a property we pretenure the
2359 // literal so it can be added as a constant function property.
2360 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2361 right->AsFunctionLiteral()->set_pretenure(true);
2362 }
2363
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002364 if (fni_ != NULL) {
2365 // Check if the right hand side is a call to avoid inferring a
2366 // name if we're dealing with "a = function(){...}();"-like
2367 // expression.
2368 if ((op == Token::INIT_VAR
2369 || op == Token::INIT_CONST
2370 || op == Token::ASSIGN)
2371 && (right->AsCall() == NULL)) {
2372 fni_->Infer();
2373 }
2374 fni_->Leave();
2375 }
2376
Ben Murdoch8b112d22011-06-08 16:22:53 +01002377 return new(zone()) Assignment(op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002378}
2379
2380
2381// Precedence = 3
2382Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2383 // ConditionalExpression ::
2384 // LogicalOrExpression
2385 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2386
2387 // We start using the binary expression parser for prec >= 4 only!
2388 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2389 if (peek() != Token::CONDITIONAL) return expression;
2390 Consume(Token::CONDITIONAL);
2391 // In parsing the first assignment expression in conditional
2392 // expressions we always accept the 'in' keyword; see ECMA-262,
2393 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002394 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002395 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2396 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002397 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002398 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002399 return new(zone()) Conditional(expression, left, right,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002400 left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002401}
2402
2403
2404static int Precedence(Token::Value tok, bool accept_IN) {
2405 if (tok == Token::IN && !accept_IN)
2406 return 0; // 0 precedence will terminate binary expression parsing
2407
2408 return Token::Precedence(tok);
2409}
2410
2411
2412// Precedence >= 4
2413Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2414 ASSERT(prec >= 4);
2415 Expression* x = ParseUnaryExpression(CHECK_OK);
2416 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2417 // prec1 >= 4
2418 while (Precedence(peek(), accept_IN) == prec1) {
2419 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002420 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002421 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2422
2423 // Compute some expressions involving only number literals.
2424 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2425 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2426 double x_val = x->AsLiteral()->handle()->Number();
2427 double y_val = y->AsLiteral()->handle()->Number();
2428
2429 switch (op) {
2430 case Token::ADD:
2431 x = NewNumberLiteral(x_val + y_val);
2432 continue;
2433 case Token::SUB:
2434 x = NewNumberLiteral(x_val - y_val);
2435 continue;
2436 case Token::MUL:
2437 x = NewNumberLiteral(x_val * y_val);
2438 continue;
2439 case Token::DIV:
2440 x = NewNumberLiteral(x_val / y_val);
2441 continue;
2442 case Token::BIT_OR:
2443 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2444 continue;
2445 case Token::BIT_AND:
2446 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2447 continue;
2448 case Token::BIT_XOR:
2449 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2450 continue;
2451 case Token::SHL: {
2452 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2453 x = NewNumberLiteral(value);
2454 continue;
2455 }
2456 case Token::SHR: {
2457 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2458 uint32_t value = DoubleToUint32(x_val) >> shift;
2459 x = NewNumberLiteral(value);
2460 continue;
2461 }
2462 case Token::SAR: {
2463 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2464 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2465 x = NewNumberLiteral(value);
2466 continue;
2467 }
2468 default:
2469 break;
2470 }
2471 }
2472
Steve Blocka7e24c12009-10-30 11:49:00 +00002473 // For now we distinguish between comparisons and other binary
2474 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002475 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002476 if (Token::IsCompareOp(op)) {
2477 // We have a comparison.
2478 Token::Value cmp = op;
2479 switch (op) {
2480 case Token::NE: cmp = Token::EQ; break;
2481 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2482 default: break;
2483 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002484 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002485 if (cmp != op) {
2486 // The comparison was negated - add a NOT.
Ben Murdoch8b112d22011-06-08 16:22:53 +01002487 x = new(zone()) UnaryOperation(Token::NOT, x);
Steve Blocka7e24c12009-10-30 11:49:00 +00002488 }
2489
2490 } else {
2491 // We have a "normal" binary operation.
Ben Murdoch8b112d22011-06-08 16:22:53 +01002492 x = new(zone()) BinaryOperation(op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002493 }
2494 }
2495 }
2496 return x;
2497}
2498
2499
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002500Expression* Parser::NewCompareNode(Token::Value op,
2501 Expression* x,
2502 Expression* y,
2503 int position) {
2504 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002505 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002506 bool is_strict = (op == Token::EQ_STRICT);
2507 Literal* x_literal = x->AsLiteral();
2508 if (x_literal != NULL && x_literal->IsNull()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002509 return new(zone()) CompareToNull(is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002510 }
2511
2512 Literal* y_literal = y->AsLiteral();
2513 if (y_literal != NULL && y_literal->IsNull()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002514 return new(zone()) CompareToNull(is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002515 }
2516 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01002517 return new(zone()) CompareOperation(op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002518}
2519
2520
Steve Blocka7e24c12009-10-30 11:49:00 +00002521Expression* Parser::ParseUnaryExpression(bool* ok) {
2522 // UnaryExpression ::
2523 // PostfixExpression
2524 // 'delete' UnaryExpression
2525 // 'void' UnaryExpression
2526 // 'typeof' UnaryExpression
2527 // '++' UnaryExpression
2528 // '--' UnaryExpression
2529 // '+' UnaryExpression
2530 // '-' UnaryExpression
2531 // '~' UnaryExpression
2532 // '!' UnaryExpression
2533
2534 Token::Value op = peek();
2535 if (Token::IsUnaryOp(op)) {
2536 op = Next();
2537 Expression* expression = ParseUnaryExpression(CHECK_OK);
2538
2539 // Compute some expressions involving only number literals.
2540 if (expression != NULL && expression->AsLiteral() &&
2541 expression->AsLiteral()->handle()->IsNumber()) {
2542 double value = expression->AsLiteral()->handle()->Number();
2543 switch (op) {
2544 case Token::ADD:
2545 return expression;
2546 case Token::SUB:
2547 return NewNumberLiteral(-value);
2548 case Token::BIT_NOT:
2549 return NewNumberLiteral(~DoubleToInt32(value));
2550 default: break;
2551 }
2552 }
2553
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002554 // "delete identifier" is a syntax error in strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01002555 if (op == Token::DELETE && top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002556 VariableProxy* operand = expression->AsVariableProxy();
2557 if (operand != NULL && !operand->is_this()) {
2558 ReportMessage("strict_delete", Vector<const char*>::empty());
2559 *ok = false;
2560 return NULL;
2561 }
2562 }
2563
Ben Murdoch8b112d22011-06-08 16:22:53 +01002564 return new(zone()) UnaryOperation(op, expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002565
2566 } else if (Token::IsCountOp(op)) {
2567 op = Next();
2568 Expression* expression = ParseUnaryExpression(CHECK_OK);
2569 // Signal a reference error if the expression is an invalid
2570 // left-hand side expression. We could report this as a syntax
2571 // error here but for compatibility with JSC we choose to report the
2572 // error at runtime.
2573 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002574 Handle<String> type =
2575 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002576 expression = NewThrowReferenceError(type);
2577 }
Steve Block1e0659c2011-05-24 12:43:12 +01002578
Steve Block44f0eee2011-05-26 01:26:41 +01002579 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002580 // Prefix expression operand in strict mode may not be eval or arguments.
2581 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2582 }
2583
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002584 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002585 return new(zone()) CountOperation(op,
2586 true /* prefix */,
2587 expression,
2588 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002589
2590 } else {
2591 return ParsePostfixExpression(ok);
2592 }
2593}
2594
2595
2596Expression* Parser::ParsePostfixExpression(bool* ok) {
2597 // PostfixExpression ::
2598 // LeftHandSideExpression ('++' | '--')?
2599
2600 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002601 if (!scanner().has_line_terminator_before_next() &&
2602 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002603 // Signal a reference error if the expression is an invalid
2604 // left-hand side expression. We could report this as a syntax
2605 // error here but for compatibility with JSC we choose to report the
2606 // error at runtime.
2607 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002608 Handle<String> type =
2609 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002610 expression = NewThrowReferenceError(type);
2611 }
Steve Block1e0659c2011-05-24 12:43:12 +01002612
Steve Block44f0eee2011-05-26 01:26:41 +01002613 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002614 // Postfix expression operand in strict mode may not be eval or arguments.
2615 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2616 }
2617
Steve Blocka7e24c12009-10-30 11:49:00 +00002618 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002619 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002620 expression =
2621 new(zone()) CountOperation(next,
2622 false /* postfix */,
2623 expression,
2624 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002625 }
2626 return expression;
2627}
2628
2629
2630Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2631 // LeftHandSideExpression ::
2632 // (NewExpression | MemberExpression) ...
2633
2634 Expression* result;
2635 if (peek() == Token::NEW) {
2636 result = ParseNewExpression(CHECK_OK);
2637 } else {
2638 result = ParseMemberExpression(CHECK_OK);
2639 }
2640
2641 while (true) {
2642 switch (peek()) {
2643 case Token::LBRACK: {
2644 Consume(Token::LBRACK);
2645 int pos = scanner().location().beg_pos;
2646 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002647 result = new(zone()) Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002648 Expect(Token::RBRACK, CHECK_OK);
2649 break;
2650 }
2651
2652 case Token::LPAREN: {
2653 int pos = scanner().location().beg_pos;
2654 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2655
2656 // Keep track of eval() calls since they disable all local variable
2657 // optimizations.
2658 // The calls that need special treatment are the
2659 // direct (i.e. not aliased) eval calls. These calls are all of the
2660 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002661 // declared in the current scope chain.
2662 // These calls are marked as potentially direct eval calls. Whether
2663 // they are actually direct calls to eval is determined at run time.
2664 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2665 // in the local scope chain. It only matters that it's called "eval",
2666 // is called without a receiver and it refers to the original eval
2667 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002668 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01002669 if (callee != NULL &&
2670 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002671 Handle<String> name = callee->name();
2672 Variable* var = top_scope_->Lookup(name);
2673 if (var == NULL) {
2674 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002675 }
2676 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002677 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002678 break;
2679 }
2680
2681 case Token::PERIOD: {
2682 Consume(Token::PERIOD);
2683 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002684 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002685 result = new(zone()) Property(result, new(zone()) Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002686 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002687 break;
2688 }
2689
2690 default:
2691 return result;
2692 }
2693 }
2694}
2695
2696
Steve Blocka7e24c12009-10-30 11:49:00 +00002697Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2698 // NewExpression ::
2699 // ('new')+ MemberExpression
2700
2701 // The grammar for new expressions is pretty warped. The keyword
2702 // 'new' can either be a part of the new expression (where it isn't
2703 // followed by an argument list) or a part of the member expression,
2704 // where it must be followed by an argument list. To accommodate
2705 // this, we parse the 'new' keywords greedily and keep track of how
2706 // many we have parsed. This information is then passed on to the
2707 // member expression parser, which is only allowed to match argument
2708 // lists as long as it has 'new' prefixes left
2709 Expect(Token::NEW, CHECK_OK);
2710 PositionStack::Element pos(stack, scanner().location().beg_pos);
2711
2712 Expression* result;
2713 if (peek() == Token::NEW) {
2714 result = ParseNewPrefix(stack, CHECK_OK);
2715 } else {
2716 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2717 }
2718
2719 if (!stack->is_empty()) {
2720 int last = stack->pop();
Ben Murdoch8b112d22011-06-08 16:22:53 +01002721 result = new(zone()) CallNew(result, new ZoneList<Expression*>(0), last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002722 }
2723 return result;
2724}
2725
2726
2727Expression* Parser::ParseNewExpression(bool* ok) {
2728 PositionStack stack(ok);
2729 return ParseNewPrefix(&stack, ok);
2730}
2731
2732
2733Expression* Parser::ParseMemberExpression(bool* ok) {
2734 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2735}
2736
2737
2738Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2739 bool* ok) {
2740 // MemberExpression ::
2741 // (PrimaryExpression | FunctionLiteral)
2742 // ('[' Expression ']' | '.' Identifier | Arguments)*
2743
2744 // Parse the initial primary or function expression.
2745 Expression* result = NULL;
2746 if (peek() == Token::FUNCTION) {
2747 Expect(Token::FUNCTION, CHECK_OK);
2748 int function_token_position = scanner().location().beg_pos;
2749 Handle<String> name;
Steve Block1e0659c2011-05-24 12:43:12 +01002750 bool is_reserved_name = false;
2751 if (peek_any_identifier()) {
2752 name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK);
2753 }
2754 result = ParseFunctionLiteral(name, is_reserved_name,
2755 function_token_position, NESTED, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002756 } else {
2757 result = ParsePrimaryExpression(CHECK_OK);
2758 }
2759
2760 while (true) {
2761 switch (peek()) {
2762 case Token::LBRACK: {
2763 Consume(Token::LBRACK);
2764 int pos = scanner().location().beg_pos;
2765 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002766 result = new(zone()) Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002767 Expect(Token::RBRACK, CHECK_OK);
2768 break;
2769 }
2770 case Token::PERIOD: {
2771 Consume(Token::PERIOD);
2772 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002773 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002774 result = new(zone()) Property(result, new(zone()) Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002775 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002776 break;
2777 }
2778 case Token::LPAREN: {
2779 if ((stack == NULL) || stack->is_empty()) return result;
2780 // Consume one of the new prefixes (already parsed).
2781 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2782 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002783 result = new CallNew(result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002784 break;
2785 }
2786 default:
2787 return result;
2788 }
2789 }
2790}
2791
2792
2793DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2794 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2795 // contexts this is used as a statement which invokes the debugger as i a
2796 // break point is present.
2797 // DebuggerStatement ::
2798 // 'debugger' ';'
2799
2800 Expect(Token::DEBUGGER, CHECK_OK);
2801 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002802 return new(zone()) DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002803}
2804
2805
2806void Parser::ReportUnexpectedToken(Token::Value token) {
2807 // We don't report stack overflows here, to avoid increasing the
2808 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002809 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002810 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002811 // Four of the tokens are treated specially
2812 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002813 case Token::EOS:
2814 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2815 case Token::NUMBER:
2816 return ReportMessage("unexpected_token_number",
2817 Vector<const char*>::empty());
2818 case Token::STRING:
2819 return ReportMessage("unexpected_token_string",
2820 Vector<const char*>::empty());
2821 case Token::IDENTIFIER:
2822 return ReportMessage("unexpected_token_identifier",
2823 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002824 case Token::FUTURE_RESERVED_WORD:
Steve Block44f0eee2011-05-26 01:26:41 +01002825 return ReportMessage(top_scope_->is_strict_mode() ?
Steve Block1e0659c2011-05-24 12:43:12 +01002826 "unexpected_strict_reserved" :
2827 "unexpected_token_identifier",
2828 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002829 default:
2830 const char* name = Token::String(token);
2831 ASSERT(name != NULL);
2832 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002833 }
2834}
2835
2836
Leon Clarkeac952652010-07-15 11:15:24 +01002837void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2838 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2839 const char* element[1] = { *name_string };
2840 ReportMessage("invalid_preparser_data",
2841 Vector<const char*>(element, 1));
2842 *ok = false;
2843}
2844
2845
Steve Blocka7e24c12009-10-30 11:49:00 +00002846Expression* Parser::ParsePrimaryExpression(bool* ok) {
2847 // PrimaryExpression ::
2848 // 'this'
2849 // 'null'
2850 // 'true'
2851 // 'false'
2852 // Identifier
2853 // Number
2854 // String
2855 // ArrayLiteral
2856 // ObjectLiteral
2857 // RegExpLiteral
2858 // '(' Expression ')'
2859
2860 Expression* result = NULL;
2861 switch (peek()) {
2862 case Token::THIS: {
2863 Consume(Token::THIS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002864 VariableProxy* recv = top_scope_->receiver();
2865 result = recv;
Steve Blocka7e24c12009-10-30 11:49:00 +00002866 break;
2867 }
2868
2869 case Token::NULL_LITERAL:
2870 Consume(Token::NULL_LITERAL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002871 result = new(zone()) Literal(isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002872 break;
2873
2874 case Token::TRUE_LITERAL:
2875 Consume(Token::TRUE_LITERAL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002876 result = new(zone()) Literal(isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002877 break;
2878
2879 case Token::FALSE_LITERAL:
2880 Consume(Token::FALSE_LITERAL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002881 result = new(zone()) Literal(isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002882 break;
2883
Steve Block1e0659c2011-05-24 12:43:12 +01002884 case Token::IDENTIFIER:
2885 case Token::FUTURE_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00002886 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002887 if (fni_ != NULL) fni_->PushVariableName(name);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002888 result = top_scope_->NewUnresolved(name,
2889 inside_with(),
2890 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002891 break;
2892 }
2893
2894 case Token::NUMBER: {
2895 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01002896 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002897 double value = StringToDouble(isolate()->unicode_cache(),
2898 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01002899 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002900 result = NewNumberLiteral(value);
2901 break;
2902 }
2903
2904 case Token::STRING: {
2905 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01002906 Handle<String> symbol = GetSymbol(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002907 result = new(zone()) Literal(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002908 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002909 break;
2910 }
2911
2912 case Token::ASSIGN_DIV:
2913 result = ParseRegExpLiteral(true, CHECK_OK);
2914 break;
2915
2916 case Token::DIV:
2917 result = ParseRegExpLiteral(false, CHECK_OK);
2918 break;
2919
2920 case Token::LBRACK:
2921 result = ParseArrayLiteral(CHECK_OK);
2922 break;
2923
2924 case Token::LBRACE:
2925 result = ParseObjectLiteral(CHECK_OK);
2926 break;
2927
2928 case Token::LPAREN:
2929 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002930 // Heuristically try to detect immediately called functions before
2931 // seeing the call parentheses.
2932 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00002933 result = ParseExpression(true, CHECK_OK);
2934 Expect(Token::RPAREN, CHECK_OK);
2935 break;
2936
2937 case Token::MOD:
2938 if (allow_natives_syntax_ || extension_ != NULL) {
2939 result = ParseV8Intrinsic(CHECK_OK);
2940 break;
2941 }
2942 // If we're not allowing special syntax we fall-through to the
2943 // default case.
2944
2945 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01002946 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00002947 ReportUnexpectedToken(tok);
2948 *ok = false;
2949 return NULL;
2950 }
2951 }
2952
2953 return result;
2954}
2955
2956
Leon Clarke4515c472010-02-03 11:58:03 +00002957void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
2958 Handle<FixedArray> literals,
2959 bool* is_simple,
2960 int* depth) {
2961 // Fill in the literals.
2962 // Accumulate output values in local variables.
2963 bool is_simple_acc = true;
2964 int depth_acc = 1;
2965 for (int i = 0; i < values->length(); i++) {
2966 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
2967 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2968 depth_acc = m_literal->depth() + 1;
2969 }
2970 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
2971 if (boilerplate_value->IsUndefined()) {
2972 literals->set_the_hole(i);
2973 is_simple_acc = false;
2974 } else {
2975 literals->set(i, *boilerplate_value);
2976 }
2977 }
2978
2979 *is_simple = is_simple_acc;
2980 *depth = depth_acc;
2981}
2982
2983
Steve Blocka7e24c12009-10-30 11:49:00 +00002984Expression* Parser::ParseArrayLiteral(bool* ok) {
2985 // ArrayLiteral ::
2986 // '[' Expression? (',' Expression?)* ']'
2987
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002988 ZoneList<Expression*>* values = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002989 Expect(Token::LBRACK, CHECK_OK);
2990 while (peek() != Token::RBRACK) {
2991 Expression* elem;
2992 if (peek() == Token::COMMA) {
2993 elem = GetLiteralTheHole();
2994 } else {
2995 elem = ParseAssignmentExpression(true, CHECK_OK);
2996 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002997 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00002998 if (peek() != Token::RBRACK) {
2999 Expect(Token::COMMA, CHECK_OK);
3000 }
3001 }
3002 Expect(Token::RBRACK, CHECK_OK);
3003
3004 // Update the scope information before the pre-parsing bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003005 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003006
Steve Blocka7e24c12009-10-30 11:49:00 +00003007 // Allocate a fixed array with all the literals.
3008 Handle<FixedArray> literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003009 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003010
3011 // Fill in the literals.
3012 bool is_simple = true;
3013 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003014 for (int i = 0, n = values->length(); i < n; i++) {
3015 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003016 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3017 depth = m_literal->depth() + 1;
3018 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003019 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003020 if (boilerplate_value->IsUndefined()) {
3021 literals->set_the_hole(i);
3022 is_simple = false;
3023 } else {
3024 literals->set(i, *boilerplate_value);
3025 }
3026 }
3027
Iain Merrick75681382010-08-19 15:07:18 +01003028 // Simple and shallow arrays can be lazily copied, we transform the
3029 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003030 if (is_simple && depth == 1 && values->length() > 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01003031 literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003032 }
3033
Ben Murdoch8b112d22011-06-08 16:22:53 +01003034 return new(zone()) ArrayLiteral(literals, values,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003035 literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003036}
3037
3038
3039bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3040 return property != NULL &&
3041 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3042}
3043
3044
3045bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003046 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003047 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3048 return lit != NULL && lit->is_simple();
3049}
3050
Iain Merrick75681382010-08-19 15:07:18 +01003051
3052bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3053 Expression* value) {
3054 // If value is a literal the property value is already set in the
3055 // boilerplate object.
3056 if (value->AsLiteral() != NULL) return false;
3057 // If value is a materialized literal the property value is already set
3058 // in the boilerplate object if it is simple.
3059 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3060 return true;
3061}
3062
3063
Steve Blocka7e24c12009-10-30 11:49:00 +00003064Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3065 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003066 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003067 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3068 if (object_literal != NULL) {
3069 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003070 if (object_literal->fast_elements()) {
3071 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3072 } else {
3073 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3074 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003075 result->set(kElementsSlot, *object_literal->constant_properties());
3076 } else {
3077 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3078 ASSERT(array_literal != NULL && array_literal->is_simple());
3079 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003080 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003081 }
3082 return result;
3083}
3084
3085
3086CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3087 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3088 return static_cast<Type>(type_value->value());
3089}
3090
3091
3092Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3093 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3094}
3095
3096
3097Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3098 if (expression->AsLiteral() != NULL) {
3099 return expression->AsLiteral()->handle();
3100 }
3101 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3102 return CompileTimeValue::GetValue(expression);
3103 }
Steve Block44f0eee2011-05-26 01:26:41 +01003104 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003105}
3106
Steve Block1e0659c2011-05-24 12:43:12 +01003107// Defined in ast.cc
3108bool IsEqualString(void* first, void* second);
3109bool IsEqualNumber(void* first, void* second);
3110
3111
3112// Validation per 11.1.5 Object Initialiser
3113class ObjectLiteralPropertyChecker {
3114 public:
3115 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3116 props(&IsEqualString),
3117 elems(&IsEqualNumber),
3118 parser_(parser),
3119 strict_(strict) {
3120 }
3121
3122 void CheckProperty(
3123 ObjectLiteral::Property* property,
3124 Scanner::Location loc,
3125 bool* ok);
3126
3127 private:
3128 enum PropertyKind {
3129 kGetAccessor = 0x01,
3130 kSetAccessor = 0x02,
3131 kAccessor = kGetAccessor | kSetAccessor,
3132 kData = 0x04
3133 };
3134
3135 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3136 switch (property->kind()) {
3137 case ObjectLiteral::Property::GETTER:
3138 return kGetAccessor;
3139 case ObjectLiteral::Property::SETTER:
3140 return kSetAccessor;
3141 default:
3142 return kData;
3143 }
3144 }
3145
3146 HashMap props;
3147 HashMap elems;
3148 Parser* parser_;
3149 bool strict_;
3150};
3151
3152
3153void ObjectLiteralPropertyChecker::CheckProperty(
3154 ObjectLiteral::Property* property,
3155 Scanner::Location loc,
3156 bool* ok) {
3157
3158 ASSERT(property != NULL);
3159
3160 Literal *lit = property->key();
3161 Handle<Object> handle = lit->handle();
3162
3163 uint32_t hash;
3164 HashMap* map;
3165 void* key;
3166
3167 if (handle->IsSymbol()) {
3168 Handle<String> name(String::cast(*handle));
3169 if (name->AsArrayIndex(&hash)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003170 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
Steve Block1e0659c2011-05-24 12:43:12 +01003171 key = key_handle.location();
3172 map = &elems;
3173 } else {
3174 key = handle.location();
3175 hash = name->Hash();
3176 map = &props;
3177 }
3178 } else if (handle->ToArrayIndex(&hash)) {
3179 key = handle.location();
3180 map = &elems;
3181 } else {
3182 ASSERT(handle->IsNumber());
3183 double num = handle->Number();
3184 char arr[100];
3185 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3186 const char* str = DoubleToCString(num, buffer);
Steve Block44f0eee2011-05-26 01:26:41 +01003187 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
Steve Block1e0659c2011-05-24 12:43:12 +01003188 key = name.location();
3189 hash = name->Hash();
3190 map = &props;
3191 }
3192
3193 // Lookup property previously defined, if any.
3194 HashMap::Entry* entry = map->Lookup(key, hash, true);
3195 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3196 intptr_t curr = GetPropertyKind(property);
3197
3198 // Duplicate data properties are illegal in strict mode.
3199 if (strict_ && (curr & prev & kData) != 0) {
3200 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3201 Vector<const char*>::empty());
3202 *ok = false;
3203 return;
3204 }
3205 // Data property conflicting with an accessor.
3206 if (((curr & kData) && (prev & kAccessor)) ||
3207 ((prev & kData) && (curr & kAccessor))) {
3208 parser_->ReportMessageAt(loc, "accessor_data_property",
3209 Vector<const char*>::empty());
3210 *ok = false;
3211 return;
3212 }
3213 // Two accessors of the same type conflicting
3214 if ((curr & prev & kAccessor) != 0) {
3215 parser_->ReportMessageAt(loc, "accessor_get_set",
3216 Vector<const char*>::empty());
3217 *ok = false;
3218 return;
3219 }
3220
3221 // Update map
3222 entry->value = reinterpret_cast<void*> (prev | curr);
3223 *ok = true;
3224}
3225
Steve Blocka7e24c12009-10-30 11:49:00 +00003226
Leon Clarke4515c472010-02-03 11:58:03 +00003227void Parser::BuildObjectLiteralConstantProperties(
3228 ZoneList<ObjectLiteral::Property*>* properties,
3229 Handle<FixedArray> constant_properties,
3230 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003231 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003232 int* depth) {
3233 int position = 0;
3234 // Accumulate the value in local variables and store it at the end.
3235 bool is_simple_acc = true;
3236 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003237 uint32_t max_element_index = 0;
3238 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003239 for (int i = 0; i < properties->length(); i++) {
3240 ObjectLiteral::Property* property = properties->at(i);
3241 if (!IsBoilerplateProperty(property)) {
3242 is_simple_acc = false;
3243 continue;
3244 }
3245 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3246 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3247 depth_acc = m_literal->depth() + 1;
3248 }
3249
3250 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3251 // value for COMPUTED properties, the real value is filled in at
3252 // runtime. The enumeration order is maintained.
3253 Handle<Object> key = property->key()->handle();
3254 Handle<Object> value = GetBoilerplateValue(property->value());
3255 is_simple_acc = is_simple_acc && !value->IsUndefined();
3256
Steve Block6ded16b2010-05-10 14:33:55 +01003257 // Keep track of the number of elements in the object literal and
3258 // the largest element index. If the largest element index is
3259 // much larger than the number of elements, creating an object
3260 // literal with fast elements will be a waste of space.
3261 uint32_t element_index = 0;
3262 if (key->IsString()
3263 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3264 && element_index > max_element_index) {
3265 max_element_index = element_index;
3266 elements++;
3267 } else if (key->IsSmi()) {
3268 int key_value = Smi::cast(*key)->value();
3269 if (key_value > 0
3270 && static_cast<uint32_t>(key_value) > max_element_index) {
3271 max_element_index = key_value;
3272 }
3273 elements++;
3274 }
3275
Leon Clarke4515c472010-02-03 11:58:03 +00003276 // Add name, value pair to the fixed array.
3277 constant_properties->set(position++, *key);
3278 constant_properties->set(position++, *value);
3279 }
Steve Block6ded16b2010-05-10 14:33:55 +01003280 *fast_elements =
3281 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003282 *is_simple = is_simple_acc;
3283 *depth = depth_acc;
3284}
3285
3286
Ben Murdochbb769b22010-08-11 14:56:33 +01003287ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3288 bool* ok) {
3289 // Special handling of getter and setter syntax:
3290 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3291 // We have already read the "get" or "set" keyword.
3292 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003293 bool is_keyword = Token::IsKeyword(next);
3294 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003295 next == Token::FUTURE_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003296 next == Token::STRING || is_keyword) {
3297 Handle<String> name;
3298 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003299 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003300 } else {
3301 name = GetSymbol(CHECK_OK);
3302 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003303 FunctionLiteral* value =
3304 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003305 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003306 RelocInfo::kNoPosition,
3307 DECLARATION,
3308 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003309 // Allow any number of parameters for compatiabilty with JSC.
3310 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003311 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003312 new(zone()) ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003313 return property;
3314 } else {
3315 ReportUnexpectedToken(next);
3316 *ok = false;
3317 return NULL;
3318 }
3319}
3320
3321
Steve Blocka7e24c12009-10-30 11:49:00 +00003322Expression* Parser::ParseObjectLiteral(bool* ok) {
3323 // ObjectLiteral ::
3324 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003325 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3326 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003327 // )*[','] '}'
3328
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003329 ZoneList<ObjectLiteral::Property*>* properties =
3330 new ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003331 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003332 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003333
Steve Block44f0eee2011-05-26 01:26:41 +01003334 ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003335
Steve Blocka7e24c12009-10-30 11:49:00 +00003336 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003337 Scanner::Location loc = scanner().location();
3338
Steve Blocka7e24c12009-10-30 11:49:00 +00003339 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003340 if (fni_ != NULL) fni_->Enter();
3341
Steve Blocka7e24c12009-10-30 11:49:00 +00003342 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003343 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003344
3345 // Location of the property name token
3346 Scanner::Location loc = scanner().peek_location();
3347
Ben Murdochbb769b22010-08-11 14:56:33 +01003348 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003349 case Token::FUTURE_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003350 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003351 bool is_getter = false;
3352 bool is_setter = false;
3353 Handle<String> id =
3354 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003355 if (fni_ != NULL) fni_->PushLiteralName(id);
3356
Ben Murdochbb769b22010-08-11 14:56:33 +01003357 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003358 // Update loc to point to the identifier
3359 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003360 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003361 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3362 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003363 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003364 }
Steve Block1e0659c2011-05-24 12:43:12 +01003365 // Validate the property.
3366 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003367 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003368 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003369
3370 if (fni_ != NULL) {
3371 fni_->Infer();
3372 fni_->Leave();
3373 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003374 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003375 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003376 // Failed to parse as get/set property, so it's just a property
3377 // called "get" or "set".
Ben Murdoch8b112d22011-06-08 16:22:53 +01003378 key = new(zone()) Literal(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003379 break;
3380 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003381 case Token::STRING: {
3382 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003383 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003384 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003385 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003386 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003387 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003388 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003389 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01003390 key = new(zone()) Literal(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003391 break;
3392 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003393 case Token::NUMBER: {
3394 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003395 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003396 double value = StringToDouble(isolate()->unicode_cache(),
3397 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003398 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003399 key = NewNumberLiteral(value);
3400 break;
3401 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003402 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003403 if (Token::IsKeyword(next)) {
3404 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003405 Handle<String> string = GetSymbol(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003406 key = new(zone()) Literal(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003407 } else {
3408 // Unexpected token.
3409 Token::Value next = Next();
3410 ReportUnexpectedToken(next);
3411 *ok = false;
3412 return NULL;
3413 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003414 }
3415
3416 Expect(Token::COLON, CHECK_OK);
3417 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3418
3419 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003420 new(zone()) ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003421
Steve Block44f0eee2011-05-26 01:26:41 +01003422 // Mark object literals that contain function literals and pretenure the
3423 // literal so it can be added as a constant function property.
3424 if (value->AsFunctionLiteral() != NULL) {
3425 has_function = true;
3426 value->AsFunctionLiteral()->set_pretenure(true);
3427 }
3428
Steve Blocka7e24c12009-10-30 11:49:00 +00003429 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3430 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003431 // Validate the property
3432 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003433 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003434
3435 // TODO(1240767): Consider allowing trailing comma.
3436 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003437
3438 if (fni_ != NULL) {
3439 fni_->Infer();
3440 fni_->Leave();
3441 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003442 }
3443 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003444
Steve Blocka7e24c12009-10-30 11:49:00 +00003445 // Computation of literal_index must happen before pre parse bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003446 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003447
Steve Block44f0eee2011-05-26 01:26:41 +01003448 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3449 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003450
Steve Blocka7e24c12009-10-30 11:49:00 +00003451 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003452 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003453 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003454 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003455 constant_properties,
3456 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003457 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003458 &depth);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003459 return new(zone()) ObjectLiteral(constant_properties,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003460 properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003461 literal_index,
3462 is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003463 fast_elements,
Steve Block44f0eee2011-05-26 01:26:41 +01003464 depth,
3465 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003466}
3467
3468
3469Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003470 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003471 Next();
3472 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3473 *ok = false;
3474 return NULL;
3475 }
3476
Steve Block44f0eee2011-05-26 01:26:41 +01003477 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003478
Steve Block9fac8402011-05-12 15:51:54 +01003479 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003480 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003481 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003482 Next();
3483
Ben Murdoch8b112d22011-06-08 16:22:53 +01003484 return new(zone()) RegExpLiteral(js_pattern, js_flags, literal_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003485}
3486
3487
3488ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3489 // Arguments ::
3490 // '(' (AssignmentExpression)*[','] ')'
3491
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003492 ZoneList<Expression*>* result = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003493 Expect(Token::LPAREN, CHECK_OK);
3494 bool done = (peek() == Token::RPAREN);
3495 while (!done) {
3496 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003497 result->Add(argument);
Steve Blocka7e24c12009-10-30 11:49:00 +00003498 done = (peek() == Token::RPAREN);
3499 if (!done) Expect(Token::COMMA, CHECK_OK);
3500 }
3501 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003502 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003503}
3504
3505
3506FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
Steve Block1e0659c2011-05-24 12:43:12 +01003507 bool name_is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003508 int function_token_position,
3509 FunctionLiteralType type,
3510 bool* ok) {
3511 // Function ::
3512 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003513 bool is_named = !var_name.is_null();
3514
3515 // The name associated with this function. If it's a function expression,
3516 // this is the actual function name, otherwise this is the name of the
3517 // variable declared and initialized with the function (expression). In
3518 // that case, we don't have a function name (it's empty).
Steve Block44f0eee2011-05-26 01:26:41 +01003519 Handle<String> name =
3520 is_named ? var_name : isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003521 // The function name, if any.
Steve Block44f0eee2011-05-26 01:26:41 +01003522 Handle<String> function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003523 if (is_named && (type == EXPRESSION || type == NESTED)) {
3524 function_name = name;
3525 }
3526
3527 int num_parameters = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +01003528 Scope* scope = NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3529 ZoneList<Statement*>* body = new ZoneList<Statement*>(8);
3530 int materialized_literal_count;
3531 int expected_property_count;
3532 int start_pos;
3533 int end_pos;
3534 bool only_simple_this_property_assignments;
3535 Handle<FixedArray> this_property_assignments;
Steve Blocka7e24c12009-10-30 11:49:00 +00003536 // Parse function body.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003537 { LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003538 top_scope_->SetScopeName(name);
3539
3540 // FormalParameterList ::
3541 // '(' (Identifier)*[','] ')'
3542 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003543 start_pos = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01003544 Scanner::Location name_loc = Scanner::NoLocation();
3545 Scanner::Location dupe_loc = Scanner::NoLocation();
3546 Scanner::Location reserved_loc = Scanner::NoLocation();
3547
Steve Blocka7e24c12009-10-30 11:49:00 +00003548 bool done = (peek() == Token::RPAREN);
3549 while (!done) {
Steve Block1e0659c2011-05-24 12:43:12 +01003550 bool is_reserved = false;
3551 Handle<String> param_name =
3552 ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
3553
3554 // Store locations for possible future error reports.
3555 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3556 name_loc = scanner().location();
3557 }
3558 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
3559 dupe_loc = scanner().location();
3560 }
3561 if (!reserved_loc.IsValid() && is_reserved) {
3562 reserved_loc = scanner().location();
3563 }
3564
3565 Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR);
3566 top_scope_->AddParameter(parameter);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003567 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003568 if (num_parameters > kMaxNumFunctionParameters) {
3569 ReportMessageAt(scanner().location(), "too_many_parameters",
3570 Vector<const char*>::empty());
3571 *ok = false;
3572 return NULL;
3573 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003574 done = (peek() == Token::RPAREN);
3575 if (!done) Expect(Token::COMMA, CHECK_OK);
3576 }
3577 Expect(Token::RPAREN, CHECK_OK);
3578
3579 Expect(Token::LBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003580
3581 // If we have a named function expression, we add a local variable
3582 // declaration to the body of the function with the name of the
3583 // function and let it refer to the function itself (closure).
3584 // NOTE: We create a proxy and resolve it here so that in the
3585 // future we can change the AST to only refer to VariableProxies
3586 // instead of Variables and Proxis as is the case now.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003587 if (!function_name.is_null() && function_name->length() > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003588 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3589 VariableProxy* fproxy =
3590 top_scope_->NewUnresolved(function_name, inside_with());
3591 fproxy->BindTo(fvar);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003592 body->Add(new(zone()) ExpressionStatement(
3593 new(zone()) Assignment(Token::INIT_CONST, fproxy,
3594 new(zone()) ThisFunction(),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003595 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003596 }
3597
3598 // Determine if the function will be lazily compiled. The mode can
3599 // only be PARSE_LAZILY if the --lazy flag is true.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003600 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3601 top_scope_->outer_scope()->is_global_scope() &&
3602 top_scope_->HasTrivialOuterContext() &&
3603 !parenthesized_function_);
3604 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003605
Ben Murdochb0fe1622011-05-05 13:52:32 +01003606 int function_block_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003607 if (is_lazily_compiled && pre_data() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003608 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003609 if (!entry.is_valid()) {
3610 ReportInvalidPreparseData(name, CHECK_OK);
3611 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003612 end_pos = entry.end_pos();
3613 if (end_pos <= function_block_pos) {
Leon Clarkeac952652010-07-15 11:15:24 +01003614 // End position greater than end of stream is safe, and hard to check.
3615 ReportInvalidPreparseData(name, CHECK_OK);
3616 }
Steve Block44f0eee2011-05-26 01:26:41 +01003617 isolate()->counters()->total_preparse_skipped()->Increment(
3618 end_pos - function_block_pos);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003619 // Seek to position just before terminal '}'.
3620 scanner().SeekForward(end_pos - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003621 materialized_literal_count = entry.literal_count();
3622 expected_property_count = entry.property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003623 only_simple_this_property_assignments = false;
Steve Block44f0eee2011-05-26 01:26:41 +01003624 this_property_assignments = isolate()->factory()->empty_fixed_array();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003625 Expect(Token::RBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003626 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003627 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3628
Steve Block44f0eee2011-05-26 01:26:41 +01003629 materialized_literal_count = lexical_scope.materialized_literal_count();
3630 expected_property_count = lexical_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003631 only_simple_this_property_assignments =
Steve Block44f0eee2011-05-26 01:26:41 +01003632 lexical_scope.only_simple_this_property_assignments();
3633 this_property_assignments = lexical_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003634
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003635 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003636 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003637 }
3638
Steve Block1e0659c2011-05-24 12:43:12 +01003639 // Validate strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01003640 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003641 if (IsEvalOrArguments(name)) {
3642 int position = function_token_position != RelocInfo::kNoPosition
3643 ? function_token_position
3644 : (start_pos > 0 ? start_pos - 1 : start_pos);
3645 Scanner::Location location = Scanner::Location(position, start_pos);
3646 ReportMessageAt(location,
3647 "strict_function_name", Vector<const char*>::empty());
3648 *ok = false;
3649 return NULL;
3650 }
3651 if (name_loc.IsValid()) {
3652 ReportMessageAt(name_loc, "strict_param_name",
3653 Vector<const char*>::empty());
3654 *ok = false;
3655 return NULL;
3656 }
3657 if (dupe_loc.IsValid()) {
3658 ReportMessageAt(dupe_loc, "strict_param_dupe",
3659 Vector<const char*>::empty());
3660 *ok = false;
3661 return NULL;
3662 }
3663 if (name_is_reserved) {
3664 int position = function_token_position != RelocInfo::kNoPosition
3665 ? function_token_position
3666 : (start_pos > 0 ? start_pos - 1 : start_pos);
3667 Scanner::Location location = Scanner::Location(position, start_pos);
3668 ReportMessageAt(location, "strict_reserved_word",
3669 Vector<const char*>::empty());
3670 *ok = false;
3671 return NULL;
3672 }
3673 if (reserved_loc.IsValid()) {
3674 ReportMessageAt(reserved_loc, "strict_reserved_word",
3675 Vector<const char*>::empty());
3676 *ok = false;
3677 return NULL;
3678 }
3679 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3680 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01003682
3683 FunctionLiteral* function_literal =
3684 new(zone()) FunctionLiteral(name,
3685 scope,
3686 body,
3687 materialized_literal_count,
3688 expected_property_count,
3689 only_simple_this_property_assignments,
3690 this_property_assignments,
3691 num_parameters,
3692 start_pos,
3693 end_pos,
3694 (function_name->length() > 0));
3695 function_literal->set_function_token_position(function_token_position);
3696
3697 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
3698 return function_literal;
Steve Blocka7e24c12009-10-30 11:49:00 +00003699}
3700
3701
3702Expression* Parser::ParseV8Intrinsic(bool* ok) {
3703 // CallRuntime ::
3704 // '%' Identifier Arguments
3705
3706 Expect(Token::MOD, CHECK_OK);
3707 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003708 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003709
3710 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003711 // The extension structures are only accessible while parsing the
3712 // very first time not when reparsing because of lazy compilation.
3713 top_scope_->ForceEagerCompilation();
3714 }
3715
Steve Block44f0eee2011-05-26 01:26:41 +01003716 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003717
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003718 // Check for built-in IS_VAR macro.
3719 if (function != NULL &&
3720 function->intrinsic_type == Runtime::RUNTIME &&
3721 function->function_id == Runtime::kIS_VAR) {
3722 // %IS_VAR(x) evaluates to x if x is a variable,
3723 // leads to a parse error otherwise. Could be implemented as an
3724 // inline function %_IS_VAR(x) to eliminate this special case.
3725 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3726 return args->at(0);
3727 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003728 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003729 *ok = false;
3730 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003731 }
3732 }
3733
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003734 // Check that the expected number of arguments are being passed.
3735 if (function != NULL &&
3736 function->nargs != -1 &&
3737 function->nargs != args->length()) {
3738 ReportMessage("illegal_access", Vector<const char*>::empty());
3739 *ok = false;
3740 return NULL;
3741 }
3742
3743 // We have a valid intrinsics call or a call to a builtin.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003744 return new(zone()) CallRuntime(name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003745}
3746
3747
Steve Block1e0659c2011-05-24 12:43:12 +01003748bool Parser::peek_any_identifier() {
3749 Token::Value next = peek();
3750 return next == Token::IDENTIFIER ||
3751 next == Token::FUTURE_RESERVED_WORD;
3752}
3753
3754
Steve Blocka7e24c12009-10-30 11:49:00 +00003755void Parser::Consume(Token::Value token) {
3756 Token::Value next = Next();
3757 USE(next);
3758 USE(token);
3759 ASSERT(next == token);
3760}
3761
3762
3763void Parser::Expect(Token::Value token, bool* ok) {
3764 Token::Value next = Next();
3765 if (next == token) return;
3766 ReportUnexpectedToken(next);
3767 *ok = false;
3768}
3769
3770
Leon Clarke4515c472010-02-03 11:58:03 +00003771bool Parser::Check(Token::Value token) {
3772 Token::Value next = peek();
3773 if (next == token) {
3774 Consume(next);
3775 return true;
3776 }
3777 return false;
3778}
3779
3780
Steve Blocka7e24c12009-10-30 11:49:00 +00003781void Parser::ExpectSemicolon(bool* ok) {
3782 // Check for automatic semicolon insertion according to
3783 // the rules given in ECMA-262, section 7.9, page 21.
3784 Token::Value tok = peek();
3785 if (tok == Token::SEMICOLON) {
3786 Next();
3787 return;
3788 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003789 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003790 tok == Token::RBRACE ||
3791 tok == Token::EOS) {
3792 return;
3793 }
3794 Expect(Token::SEMICOLON, ok);
3795}
3796
3797
3798Literal* Parser::GetLiteralUndefined() {
Ben Murdoch8b112d22011-06-08 16:22:53 +01003799 return new(zone()) Literal(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003800}
3801
3802
3803Literal* Parser::GetLiteralTheHole() {
Ben Murdoch8b112d22011-06-08 16:22:53 +01003804 return new(zone()) Literal(isolate()->factory()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003805}
3806
3807
3808Literal* Parser::GetLiteralNumber(double value) {
3809 return NewNumberLiteral(value);
3810}
3811
3812
3813Handle<String> Parser::ParseIdentifier(bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003814 bool is_reserved;
3815 return ParseIdentifierOrReservedWord(&is_reserved, ok);
3816}
3817
3818
3819Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved,
3820 bool* ok) {
3821 *is_reserved = false;
Steve Block44f0eee2011-05-26 01:26:41 +01003822 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003823 Expect(Token::IDENTIFIER, ok);
3824 } else {
3825 if (!Check(Token::IDENTIFIER)) {
3826 Expect(Token::FUTURE_RESERVED_WORD, ok);
3827 *is_reserved = true;
3828 }
3829 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003830 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003831 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003832}
3833
Ben Murdochbb769b22010-08-11 14:56:33 +01003834
3835Handle<String> Parser::ParseIdentifierName(bool* ok) {
3836 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01003837 if (next != Token::IDENTIFIER &&
3838 next != Token::FUTURE_RESERVED_WORD &&
3839 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01003840 ReportUnexpectedToken(next);
3841 *ok = false;
3842 return Handle<String>();
3843 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003844 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01003845}
3846
3847
Steve Block1e0659c2011-05-24 12:43:12 +01003848// Checks LHS expression for assignment and prefix/postfix increment/decrement
3849// in strict mode.
3850void Parser::CheckStrictModeLValue(Expression* expression,
3851 const char* error,
3852 bool* ok) {
Steve Block44f0eee2011-05-26 01:26:41 +01003853 ASSERT(top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003854 VariableProxy* lhs = expression != NULL
3855 ? expression->AsVariableProxy()
3856 : NULL;
3857
3858 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
3859 ReportMessage(error, Vector<const char*>::empty());
3860 *ok = false;
3861 }
3862}
3863
3864
3865// Checks whether octal literal last seen is between beg_pos and end_pos.
3866// If so, reports an error.
3867void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
3868 int octal = scanner().octal_position();
3869 if (beg_pos <= octal && octal <= end_pos) {
3870 ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal",
3871 Vector<const char*>::empty());
3872 scanner().clear_octal_position();
3873 *ok = false;
3874 }
3875}
3876
3877
Steve Blocka7e24c12009-10-30 11:49:00 +00003878// This function reads an identifier and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01003879// is 'get' or 'set'.
Steve Blocka7e24c12009-10-30 11:49:00 +00003880Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3881 bool* is_set,
3882 bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003883 Handle<String> result = ParseIdentifier(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003884 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01003885 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
3886 const char* token = scanner().literal_ascii_string().start();
3887 *is_get = strncmp(token, "get", 3) == 0;
3888 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003889 }
Steve Block1e0659c2011-05-24 12:43:12 +01003890 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003891}
3892
3893
3894// ----------------------------------------------------------------------------
3895// Parser support
3896
3897
3898bool Parser::TargetStackContainsLabel(Handle<String> label) {
3899 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3900 BreakableStatement* stat = t->node()->AsBreakableStatement();
3901 if (stat != NULL && ContainsLabel(stat->labels(), label))
3902 return true;
3903 }
3904 return false;
3905}
3906
3907
3908BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3909 bool anonymous = label.is_null();
3910 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3911 BreakableStatement* stat = t->node()->AsBreakableStatement();
3912 if (stat == NULL) continue;
3913 if ((anonymous && stat->is_target_for_anonymous()) ||
3914 (!anonymous && ContainsLabel(stat->labels(), label))) {
3915 RegisterTargetUse(stat->break_target(), t->previous());
3916 return stat;
3917 }
3918 }
3919 return NULL;
3920}
3921
3922
3923IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3924 bool* ok) {
3925 bool anonymous = label.is_null();
3926 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3927 IterationStatement* stat = t->node()->AsIterationStatement();
3928 if (stat == NULL) continue;
3929
3930 ASSERT(stat->is_target_for_anonymous());
3931 if (anonymous || ContainsLabel(stat->labels(), label)) {
3932 RegisterTargetUse(stat->continue_target(), t->previous());
3933 return stat;
3934 }
3935 }
3936 return NULL;
3937}
3938
3939
Ben Murdoch8b112d22011-06-08 16:22:53 +01003940void Parser::RegisterTargetUse(Label* target, Target* stop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003941 // Register that a break target found at the given stop in the
3942 // target stack has been used from the top of the target stack. Add
3943 // the break target to any TargetCollectors passed on the stack.
3944 for (Target* t = target_stack_; t != stop; t = t->previous()) {
3945 TargetCollector* collector = t->node()->AsTargetCollector();
3946 if (collector != NULL) collector->AddTarget(target);
3947 }
3948}
3949
3950
3951Literal* Parser::NewNumberLiteral(double number) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01003952 return new(zone()) Literal(isolate()->factory()->NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00003953}
3954
3955
3956Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01003957 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00003958 type, HandleVector<Object>(NULL, 0));
3959}
3960
3961
3962Expression* Parser::NewThrowSyntaxError(Handle<String> type,
3963 Handle<Object> first) {
3964 int argc = first.is_null() ? 0 : 1;
3965 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01003966 return NewThrowError(
3967 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00003968}
3969
3970
3971Expression* Parser::NewThrowTypeError(Handle<String> type,
3972 Handle<Object> first,
3973 Handle<Object> second) {
3974 ASSERT(!first.is_null() && !second.is_null());
3975 Handle<Object> elements[] = { first, second };
3976 Vector< Handle<Object> > arguments =
3977 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01003978 return NewThrowError(
3979 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00003980}
3981
3982
3983Expression* Parser::NewThrowError(Handle<String> constructor,
3984 Handle<String> type,
3985 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003986 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01003987 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
3988 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003989 for (int i = 0; i < argc; i++) {
3990 Handle<Object> element = arguments[i];
3991 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003992 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00003993 }
3994 }
Steve Block44f0eee2011-05-26 01:26:41 +01003995 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
3996 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01003997
Steve Blocka7e24c12009-10-30 11:49:00 +00003998 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003999 args->Add(new(zone()) Literal(type));
4000 args->Add(new(zone()) Literal(array));
4001 return new(zone()) Throw(new(zone()) CallRuntime(constructor, NULL, args),
Steve Blocka7e24c12009-10-30 11:49:00 +00004002 scanner().location().beg_pos);
4003}
4004
Leon Clarke4515c472010-02-03 11:58:03 +00004005// ----------------------------------------------------------------------------
4006// JSON
4007
Ben Murdochb0fe1622011-05-05 13:52:32 +01004008Handle<Object> JsonParser::ParseJson(Handle<String> script,
4009 UC16CharacterStream* source) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004010 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004011 stack_overflow_ = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004012 Handle<Object> result = ParseJsonValue();
4013 if (result.is_null() || scanner_.Next() != Token::EOS) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004014 if (stack_overflow_) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004015 // Scanner failed.
Steve Block44f0eee2011-05-26 01:26:41 +01004016 isolate()->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004017 } else {
4018 // Parse failed. Scanner's current token is the unexpected token.
4019 Token::Value token = scanner_.current_token();
4020
4021 const char* message;
4022 const char* name_opt = NULL;
4023
4024 switch (token) {
4025 case Token::EOS:
4026 message = "unexpected_eos";
4027 break;
4028 case Token::NUMBER:
4029 message = "unexpected_token_number";
4030 break;
4031 case Token::STRING:
4032 message = "unexpected_token_string";
4033 break;
4034 case Token::IDENTIFIER:
Steve Block1e0659c2011-05-24 12:43:12 +01004035 case Token::FUTURE_RESERVED_WORD:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004036 message = "unexpected_token_identifier";
4037 break;
4038 default:
4039 message = "unexpected_token";
4040 name_opt = Token::String(token);
4041 ASSERT(name_opt != NULL);
4042 break;
4043 }
4044
4045 Scanner::Location source_location = scanner_.location();
Steve Block44f0eee2011-05-26 01:26:41 +01004046 Factory* factory = isolate()->factory();
4047 MessageLocation location(factory->NewScript(script),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004048 source_location.beg_pos,
4049 source_location.end_pos);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004050 Handle<JSArray> array;
4051 if (name_opt == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +01004052 array = factory->NewJSArray(0);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004053 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004054 Handle<String> name = factory->NewStringFromUtf8(CStrVector(name_opt));
4055 Handle<FixedArray> element = factory->NewFixedArray(1);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004056 element->set(0, *name);
Steve Block44f0eee2011-05-26 01:26:41 +01004057 array = factory->NewJSArrayWithElements(element);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004058 }
Steve Block44f0eee2011-05-26 01:26:41 +01004059 Handle<Object> result = factory->NewSyntaxError(message, array);
4060 isolate()->Throw(*result, &location);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004061 return Handle<Object>::null();
4062 }
4063 }
Leon Clarke4515c472010-02-03 11:58:03 +00004064 return result;
4065}
4066
4067
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004068Handle<String> JsonParser::GetString() {
4069 int literal_length = scanner_.literal_length();
4070 if (literal_length == 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01004071 return isolate()->factory()->empty_string();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004072 }
Steve Block9fac8402011-05-12 15:51:54 +01004073 if (scanner_.is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004074 return isolate()->factory()->NewStringFromAscii(
4075 scanner_.literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +01004076 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004077 return isolate()->factory()->NewStringFromTwoByte(
4078 scanner_.literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +01004079 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004080}
4081
4082
Leon Clarke4515c472010-02-03 11:58:03 +00004083// Parse any JSON value.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004084Handle<Object> JsonParser::ParseJsonValue() {
4085 Token::Value token = scanner_.Next();
Leon Clarke4515c472010-02-03 11:58:03 +00004086 switch (token) {
Steve Block1e0659c2011-05-24 12:43:12 +01004087 case Token::STRING:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004088 return GetString();
Steve Block1e0659c2011-05-24 12:43:12 +01004089 case Token::NUMBER:
Steve Block44f0eee2011-05-26 01:26:41 +01004090 return isolate()->factory()->NewNumber(scanner_.number());
Leon Clarke4515c472010-02-03 11:58:03 +00004091 case Token::FALSE_LITERAL:
Steve Block44f0eee2011-05-26 01:26:41 +01004092 return isolate()->factory()->false_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004093 case Token::TRUE_LITERAL:
Steve Block44f0eee2011-05-26 01:26:41 +01004094 return isolate()->factory()->true_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004095 case Token::NULL_LITERAL:
Steve Block44f0eee2011-05-26 01:26:41 +01004096 return isolate()->factory()->null_value();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004097 case Token::LBRACE:
4098 return ParseJsonObject();
4099 case Token::LBRACK:
4100 return ParseJsonArray();
Leon Clarke4515c472010-02-03 11:58:03 +00004101 default:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004102 return ReportUnexpectedToken();
Leon Clarke4515c472010-02-03 11:58:03 +00004103 }
4104}
4105
4106
4107// Parse a JSON object. Scanner must be right after '{' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004108Handle<Object> JsonParser::ParseJsonObject() {
4109 Handle<JSFunction> object_constructor(
Steve Block44f0eee2011-05-26 01:26:41 +01004110 isolate()->global_context()->object_function());
4111 Handle<JSObject> json_object =
4112 isolate()->factory()->NewJSObject(object_constructor);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004113 if (scanner_.peek() == Token::RBRACE) {
4114 scanner_.Next();
4115 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004116 if (StackLimitCheck(isolate()).HasOverflowed()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004117 stack_overflow_ = true;
4118 return Handle<Object>::null();
4119 }
Leon Clarke4515c472010-02-03 11:58:03 +00004120 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004121 if (scanner_.Next() != Token::STRING) {
4122 return ReportUnexpectedToken();
4123 }
4124 Handle<String> key = GetString();
4125 if (scanner_.Next() != Token::COLON) {
4126 return ReportUnexpectedToken();
4127 }
4128 Handle<Object> value = ParseJsonValue();
4129 if (value.is_null()) return Handle<Object>::null();
Leon Clarke4515c472010-02-03 11:58:03 +00004130 uint32_t index;
4131 if (key->AsArrayIndex(&index)) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004132 SetOwnElement(json_object, index, value, kNonStrictMode);
Steve Block44f0eee2011-05-26 01:26:41 +01004133 } else if (key->Equals(isolate()->heap()->Proto_symbol())) {
Steve Block1e0659c2011-05-24 12:43:12 +01004134 // We can't remove the __proto__ accessor since it's hardcoded
4135 // in several places. Instead go along and add the value as
4136 // the prototype of the created object if possible.
4137 SetPrototype(json_object, value);
Leon Clarke4515c472010-02-03 11:58:03 +00004138 } else {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004139 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
Leon Clarke4515c472010-02-03 11:58:03 +00004140 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004141 } while (scanner_.Next() == Token::COMMA);
4142 if (scanner_.current_token() != Token::RBRACE) {
4143 return ReportUnexpectedToken();
4144 }
Leon Clarke4515c472010-02-03 11:58:03 +00004145 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004146 return json_object;
Leon Clarke4515c472010-02-03 11:58:03 +00004147}
4148
4149
4150// Parse a JSON array. Scanner must be right after '[' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004151Handle<Object> JsonParser::ParseJsonArray() {
4152 ZoneScope zone_scope(DELETE_ON_EXIT);
4153 ZoneList<Handle<Object> > elements(4);
Leon Clarke4515c472010-02-03 11:58:03 +00004154
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004155 Token::Value token = scanner_.peek();
4156 if (token == Token::RBRACK) {
4157 scanner_.Next();
4158 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004159 if (StackLimitCheck(isolate()).HasOverflowed()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004160 stack_overflow_ = true;
4161 return Handle<Object>::null();
4162 }
Leon Clarke4515c472010-02-03 11:58:03 +00004163 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004164 Handle<Object> element = ParseJsonValue();
4165 if (element.is_null()) return Handle<Object>::null();
4166 elements.Add(element);
4167 token = scanner_.Next();
4168 } while (token == Token::COMMA);
4169 if (token != Token::RBRACK) {
4170 return ReportUnexpectedToken();
4171 }
Leon Clarke4515c472010-02-03 11:58:03 +00004172 }
Leon Clarke4515c472010-02-03 11:58:03 +00004173
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004174 // Allocate a fixed array with all the elements.
4175 Handle<FixedArray> fast_elements =
Steve Block44f0eee2011-05-26 01:26:41 +01004176 isolate()->factory()->NewFixedArray(elements.length());
Leon Clarke4515c472010-02-03 11:58:03 +00004177
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004178 for (int i = 0, n = elements.length(); i < n; i++) {
4179 fast_elements->set(i, *elements[i]);
4180 }
Leon Clarke4515c472010-02-03 11:58:03 +00004181
Steve Block44f0eee2011-05-26 01:26:41 +01004182 return isolate()->factory()->NewJSArrayWithElements(fast_elements);
Leon Clarke4515c472010-02-03 11:58:03 +00004183}
4184
Steve Blocka7e24c12009-10-30 11:49:00 +00004185// ----------------------------------------------------------------------------
4186// Regular expressions
4187
4188
4189RegExpParser::RegExpParser(FlatStringReader* in,
4190 Handle<String>* error,
4191 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004192 : isolate_(Isolate::Current()),
4193 error_(error),
4194 captures_(NULL),
4195 in_(in),
4196 current_(kEndMarker),
4197 next_pos_(0),
4198 capture_count_(0),
4199 has_more_(true),
4200 multiline_(multiline),
4201 simple_(false),
4202 contains_anchor_(false),
4203 is_scanned_for_captures_(false),
4204 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004205 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004206}
4207
4208
4209uc32 RegExpParser::Next() {
4210 if (has_next()) {
4211 return in()->Get(next_pos_);
4212 } else {
4213 return kEndMarker;
4214 }
4215}
4216
4217
4218void RegExpParser::Advance() {
4219 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004220 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004221 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004222 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4223 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004224 ReportError(CStrVector("Regular expression too large"));
4225 } else {
4226 current_ = in()->Get(next_pos_);
4227 next_pos_++;
4228 }
4229 } else {
4230 current_ = kEndMarker;
4231 has_more_ = false;
4232 }
4233}
4234
4235
4236void RegExpParser::Reset(int pos) {
4237 next_pos_ = pos;
4238 Advance();
4239}
4240
4241
4242void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004243 next_pos_ += dist - 1;
4244 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004245}
4246
4247
4248bool RegExpParser::simple() {
4249 return simple_;
4250}
4251
4252RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4253 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004254 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004255 // Zip to the end to make sure the no more input is read.
4256 current_ = kEndMarker;
4257 next_pos_ = in()->length();
4258 return NULL;
4259}
4260
4261
4262// Pattern ::
4263// Disjunction
4264RegExpTree* RegExpParser::ParsePattern() {
4265 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4266 ASSERT(!has_more());
4267 // If the result of parsing is a literal string atom, and it has the
4268 // same length as the input, then the atom is identical to the input.
4269 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4270 simple_ = true;
4271 }
4272 return result;
4273}
4274
4275
4276// Disjunction ::
4277// Alternative
4278// Alternative | Disjunction
4279// Alternative ::
4280// [empty]
4281// Term Alternative
4282// Term ::
4283// Assertion
4284// Atom
4285// Atom Quantifier
4286RegExpTree* RegExpParser::ParseDisjunction() {
4287 // Used to store current state while parsing subexpressions.
4288 RegExpParserState initial_state(NULL, INITIAL, 0);
4289 RegExpParserState* stored_state = &initial_state;
4290 // Cache the builder in a local variable for quick access.
4291 RegExpBuilder* builder = initial_state.builder();
4292 while (true) {
4293 switch (current()) {
4294 case kEndMarker:
4295 if (stored_state->IsSubexpression()) {
4296 // Inside a parenthesized group when hitting end of input.
4297 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4298 }
4299 ASSERT_EQ(INITIAL, stored_state->group_type());
4300 // Parsing completed successfully.
4301 return builder->ToRegExp();
4302 case ')': {
4303 if (!stored_state->IsSubexpression()) {
4304 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4305 }
4306 ASSERT_NE(INITIAL, stored_state->group_type());
4307
4308 Advance();
4309 // End disjunction parsing and convert builder content to new single
4310 // regexp atom.
4311 RegExpTree* body = builder->ToRegExp();
4312
4313 int end_capture_index = captures_started();
4314
4315 int capture_index = stored_state->capture_index();
4316 SubexpressionType type = stored_state->group_type();
4317
4318 // Restore previous state.
4319 stored_state = stored_state->previous_state();
4320 builder = stored_state->builder();
4321
4322 // Build result of subexpression.
4323 if (type == CAPTURE) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01004324 RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004325 captures_->at(capture_index - 1) = capture;
4326 body = capture;
4327 } else if (type != GROUPING) {
4328 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4329 bool is_positive = (type == POSITIVE_LOOKAHEAD);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004330 body = new(zone()) RegExpLookahead(body,
Steve Blocka7e24c12009-10-30 11:49:00 +00004331 is_positive,
4332 end_capture_index - capture_index,
4333 capture_index);
4334 }
4335 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004336 // For compatability with JSC and ES3, we allow quantifiers after
4337 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004338 break;
4339 }
4340 case '|': {
4341 Advance();
4342 builder->NewAlternative();
4343 continue;
4344 }
4345 case '*':
4346 case '+':
4347 case '?':
4348 return ReportError(CStrVector("Nothing to repeat"));
4349 case '^': {
4350 Advance();
4351 if (multiline_) {
4352 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004353 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
Steve Blocka7e24c12009-10-30 11:49:00 +00004354 } else {
4355 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004356 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
Steve Blocka7e24c12009-10-30 11:49:00 +00004357 set_contains_anchor();
4358 }
4359 continue;
4360 }
4361 case '$': {
4362 Advance();
4363 RegExpAssertion::Type type =
4364 multiline_ ? RegExpAssertion::END_OF_LINE :
4365 RegExpAssertion::END_OF_INPUT;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004366 builder->AddAssertion(new(zone()) RegExpAssertion(type));
Steve Blocka7e24c12009-10-30 11:49:00 +00004367 continue;
4368 }
4369 case '.': {
4370 Advance();
4371 // everything except \x0a, \x0d, \u2028 and \u2029
4372 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4373 CharacterRange::AddClassEscape('.', ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004374 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004375 builder->AddAtom(atom);
4376 break;
4377 }
4378 case '(': {
4379 SubexpressionType type = CAPTURE;
4380 Advance();
4381 if (current() == '?') {
4382 switch (Next()) {
4383 case ':':
4384 type = GROUPING;
4385 break;
4386 case '=':
4387 type = POSITIVE_LOOKAHEAD;
4388 break;
4389 case '!':
4390 type = NEGATIVE_LOOKAHEAD;
4391 break;
4392 default:
4393 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4394 break;
4395 }
4396 Advance(2);
4397 } else {
4398 if (captures_ == NULL) {
4399 captures_ = new ZoneList<RegExpCapture*>(2);
4400 }
4401 if (captures_started() >= kMaxCaptures) {
4402 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4403 }
4404 captures_->Add(NULL);
4405 }
4406 // Store current state and begin new disjunction parsing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004407 stored_state = new(zone()) RegExpParserState(stored_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00004408 type,
4409 captures_started());
4410 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004411 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004412 }
4413 case '[': {
4414 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4415 builder->AddAtom(atom);
4416 break;
4417 }
4418 // Atom ::
4419 // \ AtomEscape
4420 case '\\':
4421 switch (Next()) {
4422 case kEndMarker:
4423 return ReportError(CStrVector("\\ at end of pattern"));
4424 case 'b':
4425 Advance(2);
4426 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004427 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004428 continue;
4429 case 'B':
4430 Advance(2);
4431 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004432 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004433 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004434 // AtomEscape ::
4435 // CharacterClassEscape
4436 //
4437 // CharacterClassEscape :: one of
4438 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004439 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4440 uc32 c = Next();
4441 Advance(2);
4442 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4443 CharacterRange::AddClassEscape(c, ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004444 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004445 builder->AddAtom(atom);
4446 break;
4447 }
4448 case '1': case '2': case '3': case '4': case '5': case '6':
4449 case '7': case '8': case '9': {
4450 int index = 0;
4451 if (ParseBackReferenceIndex(&index)) {
4452 RegExpCapture* capture = NULL;
4453 if (captures_ != NULL && index <= captures_->length()) {
4454 capture = captures_->at(index - 1);
4455 }
4456 if (capture == NULL) {
4457 builder->AddEmpty();
4458 break;
4459 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004460 RegExpTree* atom = new(zone()) RegExpBackReference(capture);
Steve Blocka7e24c12009-10-30 11:49:00 +00004461 builder->AddAtom(atom);
4462 break;
4463 }
4464 uc32 first_digit = Next();
4465 if (first_digit == '8' || first_digit == '9') {
4466 // Treat as identity escape
4467 builder->AddCharacter(first_digit);
4468 Advance(2);
4469 break;
4470 }
4471 }
4472 // FALLTHROUGH
4473 case '0': {
4474 Advance();
4475 uc32 octal = ParseOctalLiteral();
4476 builder->AddCharacter(octal);
4477 break;
4478 }
4479 // ControlEscape :: one of
4480 // f n r t v
4481 case 'f':
4482 Advance(2);
4483 builder->AddCharacter('\f');
4484 break;
4485 case 'n':
4486 Advance(2);
4487 builder->AddCharacter('\n');
4488 break;
4489 case 'r':
4490 Advance(2);
4491 builder->AddCharacter('\r');
4492 break;
4493 case 't':
4494 Advance(2);
4495 builder->AddCharacter('\t');
4496 break;
4497 case 'v':
4498 Advance(2);
4499 builder->AddCharacter('\v');
4500 break;
4501 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004502 Advance();
4503 uc32 controlLetter = Next();
4504 // Special case if it is an ASCII letter.
4505 // Convert lower case letters to uppercase.
4506 uc32 letter = controlLetter & ~('a' ^ 'A');
4507 if (letter < 'A' || 'Z' < letter) {
4508 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4509 // This is outside the specification. We match JSC in
4510 // reading the backslash as a literal character instead
4511 // of as starting an escape.
4512 builder->AddCharacter('\\');
4513 } else {
4514 Advance(2);
4515 builder->AddCharacter(controlLetter & 0x1f);
4516 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004517 break;
4518 }
4519 case 'x': {
4520 Advance(2);
4521 uc32 value;
4522 if (ParseHexEscape(2, &value)) {
4523 builder->AddCharacter(value);
4524 } else {
4525 builder->AddCharacter('x');
4526 }
4527 break;
4528 }
4529 case 'u': {
4530 Advance(2);
4531 uc32 value;
4532 if (ParseHexEscape(4, &value)) {
4533 builder->AddCharacter(value);
4534 } else {
4535 builder->AddCharacter('u');
4536 }
4537 break;
4538 }
4539 default:
4540 // Identity escape.
4541 builder->AddCharacter(Next());
4542 Advance(2);
4543 break;
4544 }
4545 break;
4546 case '{': {
4547 int dummy;
4548 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4549 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4550 }
4551 // fallthrough
4552 }
4553 default:
4554 builder->AddCharacter(current());
4555 Advance();
4556 break;
4557 } // end switch(current())
4558
4559 int min;
4560 int max;
4561 switch (current()) {
4562 // QuantifierPrefix ::
4563 // *
4564 // +
4565 // ?
4566 // {
4567 case '*':
4568 min = 0;
4569 max = RegExpTree::kInfinity;
4570 Advance();
4571 break;
4572 case '+':
4573 min = 1;
4574 max = RegExpTree::kInfinity;
4575 Advance();
4576 break;
4577 case '?':
4578 min = 0;
4579 max = 1;
4580 Advance();
4581 break;
4582 case '{':
4583 if (ParseIntervalQuantifier(&min, &max)) {
4584 if (max < min) {
4585 ReportError(CStrVector("numbers out of order in {} quantifier.")
4586 CHECK_FAILED);
4587 }
4588 break;
4589 } else {
4590 continue;
4591 }
4592 default:
4593 continue;
4594 }
Leon Clarkee46be812010-01-19 14:06:41 +00004595 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004596 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004597 type = RegExpQuantifier::NON_GREEDY;
4598 Advance();
4599 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4600 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4601 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004602 Advance();
4603 }
Leon Clarkee46be812010-01-19 14:06:41 +00004604 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004605 }
4606}
4607
Steve Blocka7e24c12009-10-30 11:49:00 +00004608
4609#ifdef DEBUG
4610// Currently only used in an ASSERT.
4611static bool IsSpecialClassEscape(uc32 c) {
4612 switch (c) {
4613 case 'd': case 'D':
4614 case 's': case 'S':
4615 case 'w': case 'W':
4616 return true;
4617 default:
4618 return false;
4619 }
4620}
4621#endif
4622
4623
4624// In order to know whether an escape is a backreference or not we have to scan
4625// the entire regexp and find the number of capturing parentheses. However we
4626// don't want to scan the regexp twice unless it is necessary. This mini-parser
4627// is called when needed. It can see the difference between capturing and
4628// noncapturing parentheses and can skip character classes and backslash-escaped
4629// characters.
4630void RegExpParser::ScanForCaptures() {
4631 // Start with captures started previous to current position
4632 int capture_count = captures_started();
4633 // Add count of captures after this position.
4634 int n;
4635 while ((n = current()) != kEndMarker) {
4636 Advance();
4637 switch (n) {
4638 case '\\':
4639 Advance();
4640 break;
4641 case '[': {
4642 int c;
4643 while ((c = current()) != kEndMarker) {
4644 Advance();
4645 if (c == '\\') {
4646 Advance();
4647 } else {
4648 if (c == ']') break;
4649 }
4650 }
4651 break;
4652 }
4653 case '(':
4654 if (current() != '?') capture_count++;
4655 break;
4656 }
4657 }
4658 capture_count_ = capture_count;
4659 is_scanned_for_captures_ = true;
4660}
4661
4662
4663bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4664 ASSERT_EQ('\\', current());
4665 ASSERT('1' <= Next() && Next() <= '9');
4666 // Try to parse a decimal literal that is no greater than the total number
4667 // of left capturing parentheses in the input.
4668 int start = position();
4669 int value = Next() - '0';
4670 Advance(2);
4671 while (true) {
4672 uc32 c = current();
4673 if (IsDecimalDigit(c)) {
4674 value = 10 * value + (c - '0');
4675 if (value > kMaxCaptures) {
4676 Reset(start);
4677 return false;
4678 }
4679 Advance();
4680 } else {
4681 break;
4682 }
4683 }
4684 if (value > captures_started()) {
4685 if (!is_scanned_for_captures_) {
4686 int saved_position = position();
4687 ScanForCaptures();
4688 Reset(saved_position);
4689 }
4690 if (value > capture_count_) {
4691 Reset(start);
4692 return false;
4693 }
4694 }
4695 *index_out = value;
4696 return true;
4697}
4698
4699
4700// QuantifierPrefix ::
4701// { DecimalDigits }
4702// { DecimalDigits , }
4703// { DecimalDigits , DecimalDigits }
4704//
4705// Returns true if parsing succeeds, and set the min_out and max_out
4706// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4707bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4708 ASSERT_EQ(current(), '{');
4709 int start = position();
4710 Advance();
4711 int min = 0;
4712 if (!IsDecimalDigit(current())) {
4713 Reset(start);
4714 return false;
4715 }
4716 while (IsDecimalDigit(current())) {
4717 int next = current() - '0';
4718 if (min > (RegExpTree::kInfinity - next) / 10) {
4719 // Overflow. Skip past remaining decimal digits and return -1.
4720 do {
4721 Advance();
4722 } while (IsDecimalDigit(current()));
4723 min = RegExpTree::kInfinity;
4724 break;
4725 }
4726 min = 10 * min + next;
4727 Advance();
4728 }
4729 int max = 0;
4730 if (current() == '}') {
4731 max = min;
4732 Advance();
4733 } else if (current() == ',') {
4734 Advance();
4735 if (current() == '}') {
4736 max = RegExpTree::kInfinity;
4737 Advance();
4738 } else {
4739 while (IsDecimalDigit(current())) {
4740 int next = current() - '0';
4741 if (max > (RegExpTree::kInfinity - next) / 10) {
4742 do {
4743 Advance();
4744 } while (IsDecimalDigit(current()));
4745 max = RegExpTree::kInfinity;
4746 break;
4747 }
4748 max = 10 * max + next;
4749 Advance();
4750 }
4751 if (current() != '}') {
4752 Reset(start);
4753 return false;
4754 }
4755 Advance();
4756 }
4757 } else {
4758 Reset(start);
4759 return false;
4760 }
4761 *min_out = min;
4762 *max_out = max;
4763 return true;
4764}
4765
4766
Steve Blocka7e24c12009-10-30 11:49:00 +00004767uc32 RegExpParser::ParseOctalLiteral() {
4768 ASSERT('0' <= current() && current() <= '7');
4769 // For compatibility with some other browsers (not all), we parse
4770 // up to three octal digits with a value below 256.
4771 uc32 value = current() - '0';
4772 Advance();
4773 if ('0' <= current() && current() <= '7') {
4774 value = value * 8 + current() - '0';
4775 Advance();
4776 if (value < 32 && '0' <= current() && current() <= '7') {
4777 value = value * 8 + current() - '0';
4778 Advance();
4779 }
4780 }
4781 return value;
4782}
4783
4784
4785bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4786 int start = position();
4787 uc32 val = 0;
4788 bool done = false;
4789 for (int i = 0; !done; i++) {
4790 uc32 c = current();
4791 int d = HexValue(c);
4792 if (d < 0) {
4793 Reset(start);
4794 return false;
4795 }
4796 val = val * 16 + d;
4797 Advance();
4798 if (i == length - 1) {
4799 done = true;
4800 }
4801 }
4802 *value = val;
4803 return true;
4804}
4805
4806
4807uc32 RegExpParser::ParseClassCharacterEscape() {
4808 ASSERT(current() == '\\');
4809 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4810 Advance();
4811 switch (current()) {
4812 case 'b':
4813 Advance();
4814 return '\b';
4815 // ControlEscape :: one of
4816 // f n r t v
4817 case 'f':
4818 Advance();
4819 return '\f';
4820 case 'n':
4821 Advance();
4822 return '\n';
4823 case 'r':
4824 Advance();
4825 return '\r';
4826 case 't':
4827 Advance();
4828 return '\t';
4829 case 'v':
4830 Advance();
4831 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004832 case 'c': {
4833 uc32 controlLetter = Next();
4834 uc32 letter = controlLetter & ~('A' ^ 'a');
4835 // For compatibility with JSC, inside a character class
4836 // we also accept digits and underscore as control characters.
4837 if ((controlLetter >= '0' && controlLetter <= '9') ||
4838 controlLetter == '_' ||
4839 (letter >= 'A' && letter <= 'Z')) {
4840 Advance(2);
4841 // Control letters mapped to ASCII control characters in the range
4842 // 0x00-0x1f.
4843 return controlLetter & 0x1f;
4844 }
4845 // We match JSC in reading the backslash as a literal
4846 // character instead of as starting an escape.
4847 return '\\';
4848 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004849 case '0': case '1': case '2': case '3': case '4': case '5':
4850 case '6': case '7':
4851 // For compatibility, we interpret a decimal escape that isn't
4852 // a back reference (and therefore either \0 or not valid according
4853 // to the specification) as a 1..3 digit octal character code.
4854 return ParseOctalLiteral();
4855 case 'x': {
4856 Advance();
4857 uc32 value;
4858 if (ParseHexEscape(2, &value)) {
4859 return value;
4860 }
4861 // If \x is not followed by a two-digit hexadecimal, treat it
4862 // as an identity escape.
4863 return 'x';
4864 }
4865 case 'u': {
4866 Advance();
4867 uc32 value;
4868 if (ParseHexEscape(4, &value)) {
4869 return value;
4870 }
4871 // If \u is not followed by a four-digit hexadecimal, treat it
4872 // as an identity escape.
4873 return 'u';
4874 }
4875 default: {
4876 // Extended identity escape. We accept any character that hasn't
4877 // been matched by a more specific case, not just the subset required
4878 // by the ECMAScript specification.
4879 uc32 result = current();
4880 Advance();
4881 return result;
4882 }
4883 }
4884 return 0;
4885}
4886
4887
4888CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4889 ASSERT_EQ(0, *char_class);
4890 uc32 first = current();
4891 if (first == '\\') {
4892 switch (Next()) {
4893 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4894 *char_class = Next();
4895 Advance(2);
4896 return CharacterRange::Singleton(0); // Return dummy value.
4897 }
4898 case kEndMarker:
4899 return ReportError(CStrVector("\\ at end of pattern"));
4900 default:
4901 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4902 return CharacterRange::Singleton(c);
4903 }
4904 } else {
4905 Advance();
4906 return CharacterRange::Singleton(first);
4907 }
4908}
4909
4910
Ben Murdochb0fe1622011-05-05 13:52:32 +01004911static const uc16 kNoCharClass = 0;
4912
4913// Adds range or pre-defined character class to character ranges.
4914// If char_class is not kInvalidClass, it's interpreted as a class
4915// escape (i.e., 's' means whitespace, from '\s').
4916static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4917 uc16 char_class,
4918 CharacterRange range) {
4919 if (char_class != kNoCharClass) {
4920 CharacterRange::AddClassEscape(char_class, ranges);
4921 } else {
4922 ranges->Add(range);
4923 }
4924}
4925
4926
Steve Blocka7e24c12009-10-30 11:49:00 +00004927RegExpTree* RegExpParser::ParseCharacterClass() {
4928 static const char* kUnterminated = "Unterminated character class";
4929 static const char* kRangeOutOfOrder = "Range out of order in character class";
4930
4931 ASSERT_EQ(current(), '[');
4932 Advance();
4933 bool is_negated = false;
4934 if (current() == '^') {
4935 is_negated = true;
4936 Advance();
4937 }
4938 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4939 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004940 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004941 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004942 if (current() == '-') {
4943 Advance();
4944 if (current() == kEndMarker) {
4945 // If we reach the end we break out of the loop and let the
4946 // following code report an error.
4947 break;
4948 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004949 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004950 ranges->Add(CharacterRange::Singleton('-'));
4951 break;
4952 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004953 uc16 char_class_2 = kNoCharClass;
4954 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4955 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4956 // Either end is an escaped character class. Treat the '-' verbatim.
4957 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004958 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004959 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004960 continue;
4961 }
4962 if (first.from() > next.to()) {
4963 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4964 }
4965 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4966 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004967 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004968 }
4969 }
4970 if (!has_more()) {
4971 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4972 }
4973 Advance();
4974 if (ranges->length() == 0) {
4975 ranges->Add(CharacterRange::Everything());
4976 is_negated = !is_negated;
4977 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004978 return new(zone()) RegExpCharacterClass(ranges, is_negated);
Steve Blocka7e24c12009-10-30 11:49:00 +00004979}
4980
4981
4982// ----------------------------------------------------------------------------
4983// The Parser interface.
4984
Steve Blocka7e24c12009-10-30 11:49:00 +00004985ParserMessage::~ParserMessage() {
4986 for (int i = 0; i < args().length(); i++)
4987 DeleteArray(args()[i]);
4988 DeleteArray(args().start());
4989}
4990
4991
4992ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01004993 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00004994}
4995
4996
4997int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01004998 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00004999}
5000
5001
Leon Clarkef7060e22010-06-03 12:02:55 +01005002const char* ScriptDataImpl::Data() {
5003 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00005004}
5005
5006
Leon Clarkee46be812010-01-19 14:06:41 +00005007bool ScriptDataImpl::HasError() {
5008 return has_error();
5009}
5010
5011
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005012void ScriptDataImpl::Initialize() {
5013 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005014 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5015 function_index_ = PreparseDataConstants::kHeaderSize;
5016 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5017 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005018 if (store_.length() > symbol_data_offset) {
5019 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5020 } else {
5021 // Partial preparse causes no symbol information.
5022 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5023 }
5024 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5025 }
5026}
5027
5028
5029int ScriptDataImpl::ReadNumber(byte** source) {
5030 // Reads a number from symbol_data_ in base 128. The most significant
5031 // bit marks that there are more digits.
5032 // If the first byte is 0x80 (kNumberTerminator), it would normally
5033 // represent a leading zero. Since that is useless, and therefore won't
5034 // appear as the first digit of any actual value, it is used to
5035 // mark the end of the input stream.
5036 byte* data = *source;
5037 if (data >= symbol_data_end_) return -1;
5038 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005039 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005040 // End of stream marker.
5041 return -1;
5042 }
5043 int result = input & 0x7f;
5044 data++;
5045 while ((input & 0x80u) != 0) {
5046 if (data >= symbol_data_end_) return -1;
5047 input = *data;
5048 result = (result << 7) | (input & 0x7f);
5049 data++;
5050 }
5051 *source = data;
5052 return result;
5053}
5054
5055
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005056// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005057static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005058 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01005059 ParserRecorder* recorder) {
Steve Block44f0eee2011-05-26 01:26:41 +01005060 Isolate* isolate = Isolate::Current();
Ben Murdoch8b112d22011-06-08 16:22:53 +01005061 V8JavaScriptScanner scanner(isolate->unicode_cache());
Steve Block9fac8402011-05-12 15:51:54 +01005062 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01005063 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005064 if (!preparser::PreParser::PreParseProgram(&scanner,
5065 recorder,
5066 allow_lazy,
5067 stack_limit)) {
Steve Block44f0eee2011-05-26 01:26:41 +01005068 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005069 return NULL;
5070 }
5071
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005072 // Extract the accumulated data from the recorder as a single
5073 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005074 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005075 return new ScriptDataImpl(store);
5076}
5077
5078
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005079// Preparse, but only collect data that is immediately useful,
5080// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005081ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005082 v8::Extension* extension) {
5083 bool allow_lazy = FLAG_lazy && (extension == NULL);
5084 if (!allow_lazy) {
5085 // Partial preparsing is only about lazily compiled functions.
5086 // If we don't allow lazy compilation, the log data will be empty.
5087 return NULL;
5088 }
5089 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005090 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005091}
5092
5093
Ben Murdochb0fe1622011-05-05 13:52:32 +01005094ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005095 v8::Extension* extension) {
5096 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005097 bool allow_lazy = FLAG_lazy && (extension == NULL);
5098 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005099 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005100}
5101
5102
5103bool RegExpParser::ParseRegExp(FlatStringReader* input,
5104 bool multiline,
5105 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005106 ASSERT(result != NULL);
5107 RegExpParser parser(input, &result->error, multiline);
5108 RegExpTree* tree = parser.ParsePattern();
5109 if (parser.failed()) {
5110 ASSERT(tree == NULL);
5111 ASSERT(!result->error.is_null());
5112 } else {
5113 ASSERT(tree != NULL);
5114 ASSERT(result->error.is_null());
5115 result->tree = tree;
5116 int capture_count = parser.captures_started();
5117 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5118 result->contains_anchor = parser.contains_anchor();
5119 result->capture_count = capture_count;
5120 }
5121 return !parser.failed();
5122}
5123
5124
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005125bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005126 ASSERT(info->function() == NULL);
5127 FunctionLiteral* result = NULL;
5128 Handle<Script> script = info->script();
5129 if (info->is_lazy()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005130 Parser parser(script, true, NULL, NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01005131 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00005132 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01005133 bool allow_natives_syntax =
Steve Block44f0eee2011-05-26 01:26:41 +01005134 info->allows_natives_syntax() || FLAG_allow_natives_syntax;
Ben Murdochf87a2032010-10-22 12:50:53 +01005135 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005136 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01005137 if (pre_data != NULL && pre_data->has_error()) {
5138 Scanner::Location loc = pre_data->MessageLocation();
5139 const char* message = pre_data->BuildMessage();
5140 Vector<const char*> args = pre_data->BuildArgs();
5141 parser.ReportMessageAt(loc, message, args);
5142 DeleteArray(message);
5143 for (int i = 0; i < args.length(); i++) {
5144 DeleteArray(args[i]);
5145 }
5146 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01005147 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01005148 } else {
5149 Handle<String> source = Handle<String>(String::cast(script->source()));
Steve Block1e0659c2011-05-24 12:43:12 +01005150 result = parser.ParseProgram(source,
5151 info->is_global(),
5152 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01005153 }
Leon Clarke4515c472010-02-03 11:58:03 +00005154 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005155
5156 info->SetFunction(result);
5157 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005158}
5159
Steve Blocka7e24c12009-10-30 11:49:00 +00005160} } // namespace v8::internal