blob: 13e0c33c01b12109b8af9a4eba8e22447a4ba155 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "ast.h"
32#include "bootstrapper.h"
Steve Block6ded16b2010-05-10 14:33:55 +010033#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010035#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010036#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010037#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080039#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "runtime.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010041#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "string-stream.h"
43
Kristian Monsen25f61362010-05-21 11:50:48 +010044#include "ast-inl.h"
45#include "jump-target-inl.h"
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047namespace v8 {
48namespace internal {
49
Steve Blocka7e24c12009-10-30 11:49:00 +000050// PositionStack is used for on-stack allocation of token positions for
51// new expressions. Please look at ParseNewExpression.
52
53class PositionStack {
54 public:
55 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
56 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
57
58 class Element {
59 public:
60 Element(PositionStack* stack, int value) {
61 previous_ = stack->top();
62 value_ = value;
63 stack->set_top(this);
64 }
65
66 private:
67 Element* previous() { return previous_; }
68 int value() { return value_; }
69 friend class PositionStack;
70 Element* previous_;
71 int value_;
72 };
73
74 bool is_empty() { return top_ == NULL; }
75 int pop() {
76 ASSERT(!is_empty());
77 int result = top_->value();
78 top_ = top_->previous();
79 return result;
80 }
81
82 private:
83 Element* top() { return top_; }
84 void set_top(Element* value) { top_ = value; }
85 Element* top_;
86 bool* ok_;
87};
88
89
Steve Blocka7e24c12009-10-30 11:49:00 +000090RegExpBuilder::RegExpBuilder()
91 : pending_empty_(false),
92 characters_(NULL),
93 terms_(),
94 alternatives_()
95#ifdef DEBUG
96 , last_added_(ADD_NONE)
97#endif
98 {}
99
100
101void RegExpBuilder::FlushCharacters() {
102 pending_empty_ = false;
103 if (characters_ != NULL) {
104 RegExpTree* atom = new RegExpAtom(characters_->ToConstVector());
105 characters_ = NULL;
106 text_.Add(atom);
107 LAST(ADD_ATOM);
108 }
109}
110
111
112void RegExpBuilder::FlushText() {
113 FlushCharacters();
114 int num_text = text_.length();
115 if (num_text == 0) {
116 return;
117 } else if (num_text == 1) {
118 terms_.Add(text_.last());
119 } else {
120 RegExpText* text = new RegExpText();
121 for (int i = 0; i < num_text; i++)
122 text_.Get(i)->AppendToText(text);
123 terms_.Add(text);
124 }
125 text_.Clear();
126}
127
128
129void RegExpBuilder::AddCharacter(uc16 c) {
130 pending_empty_ = false;
131 if (characters_ == NULL) {
132 characters_ = new ZoneList<uc16>(4);
133 }
134 characters_->Add(c);
135 LAST(ADD_CHAR);
136}
137
138
139void RegExpBuilder::AddEmpty() {
140 pending_empty_ = true;
141}
142
143
144void RegExpBuilder::AddAtom(RegExpTree* term) {
145 if (term->IsEmpty()) {
146 AddEmpty();
147 return;
148 }
149 if (term->IsTextElement()) {
150 FlushCharacters();
151 text_.Add(term);
152 } else {
153 FlushText();
154 terms_.Add(term);
155 }
156 LAST(ADD_ATOM);
157}
158
159
160void RegExpBuilder::AddAssertion(RegExpTree* assert) {
161 FlushText();
162 terms_.Add(assert);
163 LAST(ADD_ASSERT);
164}
165
166
167void RegExpBuilder::NewAlternative() {
168 FlushTerms();
169}
170
171
172void RegExpBuilder::FlushTerms() {
173 FlushText();
174 int num_terms = terms_.length();
175 RegExpTree* alternative;
176 if (num_terms == 0) {
177 alternative = RegExpEmpty::GetInstance();
178 } else if (num_terms == 1) {
179 alternative = terms_.last();
180 } else {
181 alternative = new RegExpAlternative(terms_.GetList());
182 }
183 alternatives_.Add(alternative);
184 terms_.Clear();
185 LAST(ADD_NONE);
186}
187
188
189RegExpTree* RegExpBuilder::ToRegExp() {
190 FlushTerms();
191 int num_alternatives = alternatives_.length();
192 if (num_alternatives == 0) {
193 return RegExpEmpty::GetInstance();
194 }
195 if (num_alternatives == 1) {
196 return alternatives_.last();
197 }
198 return new RegExpDisjunction(alternatives_.GetList());
199}
200
201
Leon Clarkee46be812010-01-19 14:06:41 +0000202void RegExpBuilder::AddQuantifierToAtom(int min,
203 int max,
204 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (pending_empty_) {
206 pending_empty_ = false;
207 return;
208 }
209 RegExpTree* atom;
210 if (characters_ != NULL) {
211 ASSERT(last_added_ == ADD_CHAR);
212 // Last atom was character.
213 Vector<const uc16> char_vector = characters_->ToConstVector();
214 int num_chars = char_vector.length();
215 if (num_chars > 1) {
216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
217 text_.Add(new RegExpAtom(prefix));
218 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219 }
220 characters_ = NULL;
221 atom = new RegExpAtom(char_vector);
222 FlushText();
223 } else if (text_.length() > 0) {
224 ASSERT(last_added_ == ADD_ATOM);
225 atom = text_.RemoveLast();
226 FlushText();
227 } else if (terms_.length() > 0) {
228 ASSERT(last_added_ == ADD_ATOM);
229 atom = terms_.RemoveLast();
230 if (atom->max_match() == 0) {
231 // Guaranteed to only match an empty string.
232 LAST(ADD_TERM);
233 if (min == 0) {
234 return;
235 }
236 terms_.Add(atom);
237 return;
238 }
239 } else {
240 // Only call immediately after adding an atom or character!
241 UNREACHABLE();
242 return;
243 }
Leon Clarkee46be812010-01-19 14:06:41 +0000244 terms_.Add(new RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 LAST(ADD_TERM);
246}
247
248
Steve 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) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 Scope* result = new Scope(parent, type);
412 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//
465// Additionlaly, it stores transient information used during parsing.
466// 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
499 void AddLoop() { loop_count_++; }
500 bool ContainsLoops() const { return loop_count_ > 0; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000501
502 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100503 // Captures the number of literals that need materialization in the
504 // function. Includes regexp literals, and boilerplate for object
505 // and array literals.
506 int materialized_literal_count_;
507
508 // Properties count estimation.
509 int expected_property_count_;
510
511 // Keeps track of assignments to properties of this. Used for
512 // optimizing constructors.
513 bool only_simple_this_property_assignments_;
514 Handle<FixedArray> this_property_assignments_;
515
516 // Captures the number of loops inside the scope.
517 int loop_count_;
518
519 // Bookkeeping
520 Parser* parser_;
521 // Previous values
522 LexicalScope* lexical_scope_parent_;
523 Scope* previous_scope_;
524 int previous_with_nesting_level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000525};
526
Steve Block44f0eee2011-05-26 01:26:41 +0100527
528LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
529 : materialized_literal_count_(0),
530 expected_property_count_(0),
531 only_simple_this_property_assignments_(false),
532 this_property_assignments_(isolate->factory()->empty_fixed_array()),
533 loop_count_(0),
534 parser_(parser),
535 lexical_scope_parent_(parser->lexical_scope_),
536 previous_scope_(parser->top_scope_),
537 previous_with_nesting_level_(parser->with_nesting_level_) {
538 parser->top_scope_ = scope;
539 parser->lexical_scope_ = this;
540 parser->with_nesting_level_ = 0;
541}
542
543
544LexicalScope::~LexicalScope() {
545 parser_->top_scope_->Leave();
546 parser_->top_scope_ = previous_scope_;
547 parser_->lexical_scope_ = lexical_scope_parent_;
548 parser_->with_nesting_level_ = previous_with_nesting_level_;
549}
550
551
Steve Blocka7e24c12009-10-30 11:49:00 +0000552// ----------------------------------------------------------------------------
553// The CHECK_OK macro is a convenient macro to enforce error
554// handling for functions that may fail (by returning !*ok).
555//
556// CAUTION: This macro appends extra statements after a call,
557// thus it must never be used where only a single statement
558// is correct (e.g. an if statement branch w/o braces)!
559
560#define CHECK_OK ok); \
561 if (!*ok) return NULL; \
562 ((void)0
563#define DUMMY ) // to make indentation work
564#undef DUMMY
565
566#define CHECK_FAILED /**/); \
567 if (failed_) return NULL; \
568 ((void)0
569#define DUMMY ) // to make indentation work
570#undef DUMMY
571
572// ----------------------------------------------------------------------------
573// Implementation of Parser
574
575Parser::Parser(Handle<Script> script,
576 bool allow_natives_syntax,
577 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000578 ScriptDataImpl* pre_data)
Steve Block44f0eee2011-05-26 01:26:41 +0100579 : isolate_(script->GetIsolate()),
580 symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800581 script_(script),
Steve Block44f0eee2011-05-26 01:26:41 +0100582 scanner_(isolate_->scanner_constants()),
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 top_scope_(NULL),
584 with_nesting_level_(0),
Steve Block44f0eee2011-05-26 01:26:41 +0100585 lexical_scope_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000586 target_stack_(NULL),
587 allow_natives_syntax_(allow_natives_syntax),
588 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100589 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100590 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100591 stack_overflow_(false),
592 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100593 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000594}
595
596
Steve Blocka7e24c12009-10-30 11:49:00 +0000597FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Block1e0659c2011-05-24 12:43:12 +0100598 bool in_global_context,
599 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000600 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
601
Steve Block44f0eee2011-05-26 01:26:41 +0100602 HistogramTimerScope timer(isolate()->counters()->parse());
603 isolate()->counters()->total_parse_size()->Increment(source->length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100604 fni_ = new FuncNameInferrer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000605
606 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100607 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100608 if (source->IsExternalTwoByteString()) {
609 // Notice that the stream is destroyed at the end of the branch block.
610 // The last line of the blocks can't be moved outside, even though they're
611 // identical calls.
612 ExternalTwoByteStringUC16CharacterStream stream(
613 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100614 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100615 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100616 } else {
617 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100618 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100619 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620 }
621}
622
623
624FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
625 bool in_global_context,
Steve Block1e0659c2011-05-24 12:43:12 +0100626 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100627 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000628 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100629 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000630
631 // Compute the parsing mode.
632 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
633 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
634
635 Scope::Type type =
636 in_global_context
637 ? Scope::GLOBAL_SCOPE
638 : Scope::EVAL_SCOPE;
Steve Block44f0eee2011-05-26 01:26:41 +0100639 Handle<String> no_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000640
641 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800642 { Scope* scope = NewScope(top_scope_, type, inside_with());
Steve Block44f0eee2011-05-26 01:26:41 +0100643 LexicalScope lexical_scope(this, scope, isolate());
Steve Block1e0659c2011-05-24 12:43:12 +0100644 if (strict_mode == kStrictMode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100645 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100646 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800647 ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000648 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100649 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800650 ParseSourceElements(body, Token::EOS, &ok);
Steve Block44f0eee2011-05-26 01:26:41 +0100651 if (ok && top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100652 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
653 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000654 if (ok) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800655 result = new FunctionLiteral(
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 no_name,
657 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800658 body,
Steve Block44f0eee2011-05-26 01:26:41 +0100659 lexical_scope.materialized_literal_count(),
660 lexical_scope.expected_property_count(),
661 lexical_scope.only_simple_this_property_assignments(),
662 lexical_scope.this_property_assignments(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000663 0,
664 0,
665 source->length(),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100666 false,
Steve Block44f0eee2011-05-26 01:26:41 +0100667 lexical_scope.ContainsLoops());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100668 } else if (stack_overflow_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100669 isolate()->StackOverflow();
Steve Blocka7e24c12009-10-30 11:49:00 +0000670 }
671 }
672
673 // Make sure the target stack is empty.
674 ASSERT(target_stack_ == NULL);
675
676 // If there was a syntax error we have to get rid of the AST
677 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100678 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 return result;
680}
681
Steve Block44f0eee2011-05-26 01:26:41 +0100682FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
Steve Block44f0eee2011-05-26 01:26:41 +0100684 HistogramTimerScope timer(isolate()->counters()->parse_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100685 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100686 isolate()->counters()->total_parse_size()->Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000687
Steve Block44f0eee2011-05-26 01:26:41 +0100688 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100689 // Initialize parser state.
690 source->TryFlatten();
691 if (source->IsExternalTwoByteString()) {
692 ExternalTwoByteStringUC16CharacterStream stream(
693 Handle<ExternalTwoByteString>::cast(source),
Steve Block44f0eee2011-05-26 01:26:41 +0100694 shared_info->start_position(),
695 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100696 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
697 return result;
698 } else {
699 GenericStringUC16CharacterStream stream(source,
Steve Block44f0eee2011-05-26 01:26:41 +0100700 shared_info->start_position(),
701 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100702 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
703 return result;
704 }
705}
706
707
Steve Block44f0eee2011-05-26 01:26:41 +0100708FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100709 UC16CharacterStream* source,
710 ZoneScope* zone_scope) {
Steve Block44f0eee2011-05-26 01:26:41 +0100711 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Steve Block9fac8402011-05-12 15:51:54 +0100712 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100713 ASSERT(target_stack_ == NULL);
714
Steve Block44f0eee2011-05-26 01:26:41 +0100715 Handle<String> name(String::cast(shared_info->name()));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100716 fni_ = new FuncNameInferrer();
717 fni_->PushEnclosingName(name);
718
Steve Blocka7e24c12009-10-30 11:49:00 +0000719 mode_ = PARSE_EAGERLY;
720
721 // Place holder for the result.
722 FunctionLiteral* result = NULL;
723
724 {
725 // Parse the function literal.
Steve Block44f0eee2011-05-26 01:26:41 +0100726 Handle<String> no_name = isolate()->factory()->empty_symbol();
727 Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
728 if (!info->closure().is_null()) {
729 scope = Scope::DeserializeScopeChain(info, scope);
730 }
731 LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000732
Steve Block44f0eee2011-05-26 01:26:41 +0100733 if (shared_info->strict_mode()) {
734 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100735 }
736
Ben Murdochf87a2032010-10-22 12:50:53 +0100737 FunctionLiteralType type =
Steve Block44f0eee2011-05-26 01:26:41 +0100738 shared_info->is_expression() ? EXPRESSION : DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000739 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100740 result = ParseFunctionLiteral(name,
741 false, // Strict mode name already checked.
742 RelocInfo::kNoPosition, type, &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000743 // Make sure the results agree.
744 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 }
746
747 // Make sure the target stack is empty.
748 ASSERT(target_stack_ == NULL);
749
750 // If there was a stack overflow we have to get rid of AST and it is
751 // not safe to do before scope has been deleted.
752 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100753 zone_scope->DeleteOnExit();
Steve Block44f0eee2011-05-26 01:26:41 +0100754 if (stack_overflow_) isolate()->StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100755 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100756 Handle<String> inferred_name(shared_info->inferred_name());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100757 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000758 }
759 return result;
760}
761
Ben Murdochf87a2032010-10-22 12:50:53 +0100762
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800763Handle<String> Parser::GetSymbol(bool* ok) {
764 int symbol_id = -1;
765 if (pre_data() != NULL) {
766 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000767 }
Steve Block9fac8402011-05-12 15:51:54 +0100768 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000769}
Steve Blocka7e24c12009-10-30 11:49:00 +0000770
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800771
Steve Blocka7e24c12009-10-30 11:49:00 +0000772void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100773 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000774 ReportMessageAt(source_location, type, args);
775}
776
777
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800778void Parser::ReportMessageAt(Scanner::Location source_location,
779 const char* type,
780 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000781 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100782 source_location.beg_pos,
783 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100784 Factory* factory = isolate()->factory();
785 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000786 for (int i = 0; i < args.length(); i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100787 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100788 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000789 }
Steve Block44f0eee2011-05-26 01:26:41 +0100790 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
791 Handle<Object> result = factory->NewSyntaxError(type, array);
792 isolate()->Throw(*result, &location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000793}
794
795
Ben Murdochb8e0da22011-05-16 14:20:40 +0100796void Parser::ReportMessageAt(Scanner::Location source_location,
797 const char* type,
798 Vector<Handle<String> > args) {
799 MessageLocation location(script_,
800 source_location.beg_pos,
801 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100802 Factory* factory = isolate()->factory();
803 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100804 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100805 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100806 }
Steve Block44f0eee2011-05-26 01:26:41 +0100807 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
808 Handle<Object> result = factory->NewSyntaxError(type, array);
809 isolate()->Throw(*result, &location);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100810}
811
812
Steve Blocka7e24c12009-10-30 11:49:00 +0000813// Base class containing common code for the different finder classes used by
814// the parser.
815class ParserFinder {
816 protected:
817 ParserFinder() {}
818 static Assignment* AsAssignment(Statement* stat) {
819 if (stat == NULL) return NULL;
820 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
821 if (exp_stat == NULL) return NULL;
822 return exp_stat->expression()->AsAssignment();
823 }
824};
825
826
827// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000828// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000829class InitializationBlockFinder : public ParserFinder {
830 public:
831 InitializationBlockFinder()
832 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
833
834 ~InitializationBlockFinder() {
835 if (InBlock()) EndBlock();
836 }
837
838 void Update(Statement* stat) {
839 Assignment* assignment = AsAssignment(stat);
840 if (InBlock()) {
841 if (BlockContinues(assignment)) {
842 UpdateBlock(assignment);
843 } else {
844 EndBlock();
845 }
846 }
847 if (!InBlock() && (assignment != NULL) &&
848 (assignment->op() == Token::ASSIGN)) {
849 StartBlock(assignment);
850 }
851 }
852
853 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800854 // The minimum number of contiguous assignment that will
855 // be treated as an initialization block. Benchmarks show that
856 // the overhead exceeds the savings below this limit.
857 static const int kMinInitializationBlock = 3;
858
Steve Blocka7e24c12009-10-30 11:49:00 +0000859 // Returns true if the expressions appear to denote the same object.
860 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000861 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000862 static bool SameObject(Expression* e1, Expression* e2) {
863 VariableProxy* v1 = e1->AsVariableProxy();
864 VariableProxy* v2 = e2->AsVariableProxy();
865 if (v1 != NULL && v2 != NULL) {
866 return v1->name()->Equals(*v2->name());
867 }
868 Property* p1 = e1->AsProperty();
869 Property* p2 = e2->AsProperty();
870 if ((p1 == NULL) || (p2 == NULL)) return false;
871 Literal* key1 = p1->key()->AsLiteral();
872 Literal* key2 = p2->key()->AsLiteral();
873 if ((key1 == NULL) || (key2 == NULL)) return false;
874 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
875 return false;
876 }
877 String* name1 = String::cast(*key1->handle());
878 String* name2 = String::cast(*key2->handle());
879 if (!name1->Equals(name2)) return false;
880 return SameObject(p1->obj(), p2->obj());
881 }
882
883 // Returns true if the expressions appear to denote different properties
884 // of the same object.
885 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
886 Property* p1 = e1->AsProperty();
887 Property* p2 = e2->AsProperty();
888 if ((p1 == NULL) || (p2 == NULL)) return false;
889 return SameObject(p1->obj(), p2->obj());
890 }
891
892 bool BlockContinues(Assignment* assignment) {
893 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
894 if (assignment->op() != Token::ASSIGN) return false;
895 return PropertyOfSameObject(first_in_block_->target(),
896 assignment->target());
897 }
898
899 void StartBlock(Assignment* assignment) {
900 first_in_block_ = assignment;
901 last_in_block_ = assignment;
902 block_size_ = 1;
903 }
904
905 void UpdateBlock(Assignment* assignment) {
906 last_in_block_ = assignment;
907 ++block_size_;
908 }
909
910 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800911 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000912 first_in_block_->mark_block_start();
913 last_in_block_->mark_block_end();
914 }
915 last_in_block_ = first_in_block_ = NULL;
916 block_size_ = 0;
917 }
918
919 bool InBlock() { return first_in_block_ != NULL; }
920
921 Assignment* first_in_block_;
922 Assignment* last_in_block_;
923 int block_size_;
924
925 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
926};
927
928
929// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
930// this.x = ...;, where x is a named property. It also determines whether a
931// function contains only assignments of this type.
932class ThisNamedPropertyAssigmentFinder : public ParserFinder {
933 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100934 explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate)
935 : isolate_(isolate),
936 only_simple_this_property_assignments_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000937 names_(NULL),
938 assigned_arguments_(NULL),
939 assigned_constants_(NULL) {}
940
941 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000942 // Bail out if function already has property assignment that are
943 // not simple this property assignments.
944 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000945 return;
946 }
947
948 // Check whether this statement is of the form this.x = ...;
949 Assignment* assignment = AsAssignment(stat);
950 if (IsThisPropertyAssignment(assignment)) {
951 HandleThisPropertyAssignment(scope, assignment);
952 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 only_simple_this_property_assignments_ = false;
954 }
955 }
956
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 // Returns whether only statements of the form this.x = y; where y is either a
958 // constant or a function argument was encountered.
959 bool only_simple_this_property_assignments() {
960 return only_simple_this_property_assignments_;
961 }
962
963 // Returns a fixed array containing three elements for each assignment of the
964 // form this.x = y;
965 Handle<FixedArray> GetThisPropertyAssignments() {
966 if (names_ == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100967 return isolate_->factory()->empty_fixed_array();
Steve Blocka7e24c12009-10-30 11:49:00 +0000968 }
969 ASSERT(names_ != NULL);
970 ASSERT(assigned_arguments_ != NULL);
971 ASSERT_EQ(names_->length(), assigned_arguments_->length());
972 ASSERT_EQ(names_->length(), assigned_constants_->length());
973 Handle<FixedArray> assignments =
Steve Block44f0eee2011-05-26 01:26:41 +0100974 isolate_->factory()->NewFixedArray(names_->length() * 3);
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 for (int i = 0; i < names_->length(); i++) {
976 assignments->set(i * 3, *names_->at(i));
977 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
978 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
979 }
980 return assignments;
981 }
982
983 private:
984 bool IsThisPropertyAssignment(Assignment* assignment) {
985 if (assignment != NULL) {
986 Property* property = assignment->target()->AsProperty();
987 return assignment->op() == Token::ASSIGN
988 && property != NULL
989 && property->obj()->AsVariableProxy() != NULL
990 && property->obj()->AsVariableProxy()->is_this();
991 }
992 return false;
993 }
994
995 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +0100996 // Check that the property assigned to is a named property, which is not
997 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +0000998 Property* property = assignment->target()->AsProperty();
999 ASSERT(property != NULL);
1000 Literal* literal = property->key()->AsLiteral();
1001 uint32_t dummy;
1002 if (literal != NULL &&
1003 literal->handle()->IsString() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001004 !String::cast(*(literal->handle()))->Equals(
1005 isolate_->heap()->Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001006 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1007 Handle<String> key = Handle<String>::cast(literal->handle());
1008
1009 // Check whether the value assigned is either a constant or matches the
1010 // name of one of the arguments to the function.
1011 if (assignment->value()->AsLiteral() != NULL) {
1012 // Constant assigned.
1013 Literal* literal = assignment->value()->AsLiteral();
1014 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001015 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 } else if (assignment->value()->AsVariableProxy() != NULL) {
1017 // Variable assigned.
1018 Handle<String> name =
1019 assignment->value()->AsVariableProxy()->name();
1020 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 for (int i = 0; i < scope->num_parameters(); i++) {
1022 if (*scope->parameter(i)->name() == *name) {
1023 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001024 AssignmentFromParameter(key, i);
1025 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001026 }
1027 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001028 }
1029 }
Steve Blockd0582a62009-12-15 09:54:21 +00001030 // It is not a simple "this.x = value;" assignment with a constant
1031 // or parameter value.
1032 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 }
1034
1035 void AssignmentFromParameter(Handle<String> name, int index) {
1036 EnsureAllocation();
1037 names_->Add(name);
1038 assigned_arguments_->Add(index);
Steve Block44f0eee2011-05-26 01:26:41 +01001039 assigned_constants_->Add(isolate_->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001040 }
1041
1042 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
1043 EnsureAllocation();
1044 names_->Add(name);
1045 assigned_arguments_->Add(-1);
1046 assigned_constants_->Add(value);
1047 }
1048
Steve Blockd0582a62009-12-15 09:54:21 +00001049 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001050 // The this assignment is not a simple one.
1051 only_simple_this_property_assignments_ = false;
1052 }
1053
1054 void EnsureAllocation() {
1055 if (names_ == NULL) {
1056 ASSERT(assigned_arguments_ == NULL);
1057 ASSERT(assigned_constants_ == NULL);
1058 names_ = new ZoneStringList(4);
1059 assigned_arguments_ = new ZoneList<int>(4);
1060 assigned_constants_ = new ZoneObjectList(4);
1061 }
1062 }
1063
Steve Block44f0eee2011-05-26 01:26:41 +01001064 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001065 bool only_simple_this_property_assignments_;
1066 ZoneStringList* names_;
1067 ZoneList<int>* assigned_arguments_;
1068 ZoneObjectList* assigned_constants_;
1069};
1070
1071
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001072void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001073 int end_token,
1074 bool* ok) {
1075 // SourceElements ::
1076 // (Statement)* <end_token>
1077
1078 // Allocate a target stack to use for this set of source
1079 // elements. This way, all scripts and functions get their own
1080 // target stack thus avoiding illegal breaks and continues across
1081 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001082 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001083
1084 ASSERT(processor != NULL);
1085 InitializationBlockFinder block_finder;
Steve Block44f0eee2011-05-26 01:26:41 +01001086 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
Steve Block1e0659c2011-05-24 12:43:12 +01001087 bool directive_prologue = true; // Parsing directive prologue.
1088
Steve Blocka7e24c12009-10-30 11:49:00 +00001089 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001090 if (directive_prologue && peek() != Token::STRING) {
1091 directive_prologue = false;
1092 }
1093
1094 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001095
1096 Statement* stat;
1097 if (peek() == Token::FUNCTION) {
1098 // FunctionDeclaration is only allowed in the context of SourceElements
1099 // (Ecma 262 5th Edition, clause 14):
1100 // SourceElement:
1101 // Statement
1102 // FunctionDeclaration
1103 // Common language extension is to allow function declaration in place
1104 // of any statement. This language extension is disabled in strict mode.
1105 stat = ParseFunctionDeclaration(CHECK_OK);
1106 } else {
1107 stat = ParseStatement(NULL, CHECK_OK);
1108 }
Steve Block1e0659c2011-05-24 12:43:12 +01001109
1110 if (stat == NULL || stat->IsEmpty()) {
1111 directive_prologue = false; // End of directive prologue.
1112 continue;
1113 }
1114
1115 if (directive_prologue) {
1116 // A shot at a directive.
1117 ExpressionStatement *e_stat;
1118 Literal *literal;
1119 // Still processing directive prologue?
1120 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1121 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1122 literal->handle()->IsString()) {
1123 Handle<String> directive = Handle<String>::cast(literal->handle());
1124
1125 // Check "use strict" directive (ES5 14.1).
Steve Block44f0eee2011-05-26 01:26:41 +01001126 if (!top_scope_->is_strict_mode() &&
1127 directive->Equals(isolate()->heap()->use_strict()) &&
Steve Block1e0659c2011-05-24 12:43:12 +01001128 token_loc.end_pos - token_loc.beg_pos ==
Steve Block44f0eee2011-05-26 01:26:41 +01001129 isolate()->heap()->use_strict()->length() + 2) {
1130 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +01001131 // "use strict" is the only directive for now.
1132 directive_prologue = false;
1133 }
1134 } else {
1135 // End of the directive prologue.
1136 directive_prologue = false;
1137 }
1138 }
1139
Steve Blocka7e24c12009-10-30 11:49:00 +00001140 // We find and mark the initialization blocks on top level code only.
1141 // This is because the optimization prevents reuse of the map transitions,
1142 // so it should be used only for code that will only be run once.
1143 if (top_scope_->is_global_scope()) {
1144 block_finder.Update(stat);
1145 }
1146 // Find and mark all assignments to named properties in this (this.x =)
1147 if (top_scope_->is_function_scope()) {
1148 this_property_assignment_finder.Update(top_scope_, stat);
1149 }
1150 processor->Add(stat);
1151 }
1152
1153 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001154 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001155 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001156 this_property_assignment_finder.only_simple_this_property_assignments()
1157 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001158 if (only_simple_this_property_assignments) {
Steve Block44f0eee2011-05-26 01:26:41 +01001159 lexical_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001160 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001161 this_property_assignment_finder.GetThisPropertyAssignments());
1162 }
1163 }
1164 return 0;
1165}
1166
1167
1168Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1169 // Statement ::
1170 // Block
1171 // VariableStatement
1172 // EmptyStatement
1173 // ExpressionStatement
1174 // IfStatement
1175 // IterationStatement
1176 // ContinueStatement
1177 // BreakStatement
1178 // ReturnStatement
1179 // WithStatement
1180 // LabelledStatement
1181 // SwitchStatement
1182 // ThrowStatement
1183 // TryStatement
1184 // DebuggerStatement
1185
1186 // Note: Since labels can only be used by 'break' and 'continue'
1187 // statements, which themselves are only valid within blocks,
1188 // iterations or 'switch' statements (i.e., BreakableStatements),
1189 // labels can be simply ignored in all other cases; except for
1190 // trivial labeled break statements 'label: break label' which is
1191 // parsed into an empty statement.
1192
1193 // Keep the source position of the statement
1194 int statement_pos = scanner().peek_location().beg_pos;
1195 Statement* stmt = NULL;
1196 switch (peek()) {
1197 case Token::LBRACE:
1198 return ParseBlock(labels, ok);
1199
1200 case Token::CONST: // fall through
1201 case Token::VAR:
1202 stmt = ParseVariableStatement(ok);
1203 break;
1204
1205 case Token::SEMICOLON:
1206 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001207 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001208
1209 case Token::IF:
1210 stmt = ParseIfStatement(labels, ok);
1211 break;
1212
1213 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001214 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 break;
1216
1217 case Token::WHILE:
1218 stmt = ParseWhileStatement(labels, ok);
1219 break;
1220
1221 case Token::FOR:
1222 stmt = ParseForStatement(labels, ok);
1223 break;
1224
1225 case Token::CONTINUE:
1226 stmt = ParseContinueStatement(ok);
1227 break;
1228
1229 case Token::BREAK:
1230 stmt = ParseBreakStatement(labels, ok);
1231 break;
1232
1233 case Token::RETURN:
1234 stmt = ParseReturnStatement(ok);
1235 break;
1236
1237 case Token::WITH:
1238 stmt = ParseWithStatement(labels, ok);
1239 break;
1240
1241 case Token::SWITCH:
1242 stmt = ParseSwitchStatement(labels, ok);
1243 break;
1244
1245 case Token::THROW:
1246 stmt = ParseThrowStatement(ok);
1247 break;
1248
1249 case Token::TRY: {
1250 // NOTE: It is somewhat complicated to have labels on
1251 // try-statements. When breaking out of a try-finally statement,
1252 // one must take great care not to treat it as a
1253 // fall-through. It is much easier just to wrap the entire
1254 // try-statement in a statement block and put the labels there
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001255 Block* result = new Block(labels, 1, false);
1256 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001257 TryStatement* statement = ParseTryStatement(CHECK_OK);
1258 if (statement) {
1259 statement->set_statement_pos(statement_pos);
1260 }
1261 if (result) result->AddStatement(statement);
1262 return result;
1263 }
1264
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001265 case Token::FUNCTION: {
1266 // In strict mode, FunctionDeclaration is only allowed in the context
1267 // of SourceElements.
Steve Block44f0eee2011-05-26 01:26:41 +01001268 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001269 ReportMessageAt(scanner().peek_location(), "strict_function",
1270 Vector<const char*>::empty());
1271 *ok = false;
1272 return NULL;
1273 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001274 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001275 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001276
1277 case Token::NATIVE:
1278 return ParseNativeDeclaration(ok);
1279
1280 case Token::DEBUGGER:
1281 stmt = ParseDebuggerStatement(ok);
1282 break;
1283
1284 default:
1285 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1286 }
1287
1288 // Store the source position of the statement
1289 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1290 return stmt;
1291}
1292
1293
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001294VariableProxy* Parser::Declare(Handle<String> name,
1295 Variable::Mode mode,
1296 FunctionLiteral* fun,
1297 bool resolve,
1298 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001299 Variable* var = NULL;
1300 // If we are inside a function, a declaration of a variable
1301 // is a truly local variable, and the scope of the variable
1302 // is always the function scope.
1303
1304 // If a function scope exists, then we can statically declare this
1305 // variable and also set its mode. In any case, a Declaration node
1306 // will be added to the scope so that the declaration can be added
1307 // to the corresponding activation frame at runtime if necessary.
1308 // For instance declarations inside an eval scope need to be added
1309 // to the calling function context.
1310 if (top_scope_->is_function_scope()) {
1311 // Declare the variable in the function scope.
1312 var = top_scope_->LocalLookup(name);
1313 if (var == NULL) {
1314 // Declare the name.
1315 var = top_scope_->DeclareLocal(name, mode);
1316 } else {
1317 // The name was declared before; check for conflicting
1318 // re-declarations. If the previous declaration was a const or the
1319 // current declaration is a const then we have a conflict. There is
1320 // similar code in runtime.cc in the Declare functions.
1321 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1322 // We only have vars and consts in declarations.
1323 ASSERT(var->mode() == Variable::VAR ||
1324 var->mode() == Variable::CONST);
1325 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1326 Handle<String> type_string =
Steve Block44f0eee2011-05-26 01:26:41 +01001327 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001328 Expression* expression =
Steve Block44f0eee2011-05-26 01:26:41 +01001329 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00001330 type_string, name);
1331 top_scope_->SetIllegalRedeclaration(expression);
1332 }
1333 }
1334 }
1335
1336 // We add a declaration node for every declaration. The compiler
1337 // will only generate code if necessary. In particular, declarations
1338 // for inner local variables that do not represent functions won't
1339 // result in any generated code.
1340 //
1341 // Note that we always add an unresolved proxy even if it's not
1342 // used, simply because we don't know in this method (w/o extra
1343 // parameters) if the proxy is needed or not. The proxy will be
1344 // bound during variable resolution time unless it was pre-bound
1345 // below.
1346 //
1347 // WARNING: This will lead to multiple declaration nodes for the
1348 // same variable if it is declared several times. This is not a
1349 // semantic issue as long as we keep the source order, but it may be
1350 // a performance issue since it may lead to repeated
1351 // Runtime::DeclareContextSlot() calls.
1352 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001353 top_scope_->AddDeclaration(new Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001354
1355 // For global const variables we bind the proxy to a variable.
1356 if (mode == Variable::CONST && top_scope_->is_global_scope()) {
1357 ASSERT(resolve); // should be set by all callers
1358 Variable::Kind kind = Variable::NORMAL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001359 var = new Variable(top_scope_, name, Variable::CONST, true, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001360 }
1361
1362 // If requested and we have a local variable, bind the proxy to the variable
1363 // at parse-time. This is used for functions (and consts) declared inside
1364 // statements: the corresponding function (or const) variable must be in the
1365 // function scope and not a statement-local scope, e.g. as provided with a
1366 // 'with' statement:
1367 //
1368 // with (obj) {
1369 // function f() {}
1370 // }
1371 //
1372 // which is translated into:
1373 //
1374 // with (obj) {
1375 // // in this case this is not: 'var f; f = function () {};'
1376 // var f = function () {};
1377 // }
1378 //
1379 // Note that if 'f' is accessed from inside the 'with' statement, it
1380 // will be allocated in the context (because we must be able to look
1381 // it up dynamically) but it will also be accessed statically, i.e.,
1382 // with a context slot index and a context chain length for this
1383 // initialization code. Thus, inside the 'with' statement, we need
1384 // both access to the static and the dynamic context chain; the
1385 // runtime needs to provide both.
1386 if (resolve && var != NULL) proxy->BindTo(var);
1387
1388 return proxy;
1389}
1390
1391
1392// Language extension which is only enabled for source files loaded
1393// through the API's extension mechanism. A native function
1394// declaration is resolved by looking up the function through a
1395// callback provided by the extension.
1396Statement* Parser::ParseNativeDeclaration(bool* ok) {
1397 if (extension_ == NULL) {
1398 ReportUnexpectedToken(Token::NATIVE);
1399 *ok = false;
1400 return NULL;
1401 }
1402
1403 Expect(Token::NATIVE, CHECK_OK);
1404 Expect(Token::FUNCTION, CHECK_OK);
1405 Handle<String> name = ParseIdentifier(CHECK_OK);
1406 Expect(Token::LPAREN, CHECK_OK);
1407 bool done = (peek() == Token::RPAREN);
1408 while (!done) {
1409 ParseIdentifier(CHECK_OK);
1410 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001411 if (!done) {
1412 Expect(Token::COMMA, CHECK_OK);
1413 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 }
1415 Expect(Token::RPAREN, CHECK_OK);
1416 Expect(Token::SEMICOLON, CHECK_OK);
1417
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 // Make sure that the function containing the native declaration
1419 // isn't lazily compiled. The extension structures are only
1420 // accessible while parsing the first time not when reparsing
1421 // because of lazy compilation.
1422 top_scope_->ForceEagerCompilation();
1423
1424 // Compute the function template for the native function.
1425 v8::Handle<v8::FunctionTemplate> fun_template =
1426 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1427 ASSERT(!fun_template.IsEmpty());
1428
Steve Block6ded16b2010-05-10 14:33:55 +01001429 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001430 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1431 const int literals = fun->NumberOfLiterals();
1432 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001433 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001434 Handle<SharedFunctionInfo> shared =
Steve Block44f0eee2011-05-26 01:26:41 +01001435 isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001436 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001437 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001438
Steve Block6ded16b2010-05-10 14:33:55 +01001439 // Copy the function data to the shared function info.
1440 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001441 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001442 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001443
1444 // TODO(1240846): It's weird that native function declarations are
1445 // introduced dynamically when we meet their declarations, whereas
1446 // other functions are setup when entering the surrounding scope.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001447 SharedFunctionInfoLiteral* lit = new SharedFunctionInfoLiteral(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001448 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001449 return new ExpressionStatement(
1450 new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001451}
1452
1453
1454Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1455 // FunctionDeclaration ::
1456 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1457 Expect(Token::FUNCTION, CHECK_OK);
1458 int function_token_position = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01001459 bool is_reserved = false;
1460 Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 FunctionLiteral* fun = ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01001462 is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001463 function_token_position,
1464 DECLARATION,
1465 CHECK_OK);
1466 // Even if we're not at the top-level of the global or a function
1467 // scope, we treat is as such and introduce the function with it's
1468 // initial value upon entering the corresponding scope.
1469 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001470 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001471}
1472
1473
1474Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1475 // Block ::
1476 // '{' Statement* '}'
1477
1478 // Note that a Block does not introduce a new execution scope!
1479 // (ECMA-262, 3rd, 12.2)
1480 //
1481 // Construct block expecting 16 statements.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001482 Block* result = new Block(labels, 16, false);
1483 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001484 Expect(Token::LBRACE, CHECK_OK);
1485 while (peek() != Token::RBRACE) {
1486 Statement* stat = ParseStatement(NULL, CHECK_OK);
1487 if (stat && !stat->IsEmpty()) result->AddStatement(stat);
1488 }
1489 Expect(Token::RBRACE, CHECK_OK);
1490 return result;
1491}
1492
1493
1494Block* Parser::ParseVariableStatement(bool* ok) {
1495 // VariableStatement ::
1496 // VariableDeclarations ';'
1497
1498 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature
1499 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK);
1500 ExpectSemicolon(CHECK_OK);
1501 return result;
1502}
1503
Steve Block44f0eee2011-05-26 01:26:41 +01001504
1505bool Parser::IsEvalOrArguments(Handle<String> string) {
1506 return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
1507 string.is_identical_to(isolate()->factory()->arguments_symbol());
Steve Block1e0659c2011-05-24 12:43:12 +01001508}
Steve Blocka7e24c12009-10-30 11:49:00 +00001509
Steve Block44f0eee2011-05-26 01:26:41 +01001510
Steve Blocka7e24c12009-10-30 11:49:00 +00001511// If the variable declaration declares exactly one non-const
1512// variable, then *var is set to that variable. In all other cases,
1513// *var is untouched; in particular, it is the caller's responsibility
1514// to initialize it properly. This mechanism is used for the parsing
1515// of 'for-in' loops.
1516Block* Parser::ParseVariableDeclarations(bool accept_IN,
1517 Expression** var,
1518 bool* ok) {
1519 // VariableDeclarations ::
1520 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1521
1522 Variable::Mode mode = Variable::VAR;
1523 bool is_const = false;
1524 if (peek() == Token::VAR) {
1525 Consume(Token::VAR);
1526 } else if (peek() == Token::CONST) {
1527 Consume(Token::CONST);
Steve Block44f0eee2011-05-26 01:26:41 +01001528 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001529 ReportMessage("strict_const", Vector<const char*>::empty());
1530 *ok = false;
1531 return NULL;
1532 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001533 mode = Variable::CONST;
1534 is_const = true;
1535 } else {
1536 UNREACHABLE(); // by current callers
1537 }
1538
1539 // The scope of a variable/const declared anywhere inside a function
1540 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1541 // transform a source-level variable/const declaration into a (Function)
1542 // Scope declaration, and rewrite the source-level initialization into an
1543 // assignment statement. We use a block to collect multiple assignments.
1544 //
1545 // We mark the block as initializer block because we don't want the
1546 // rewriter to add a '.result' assignment to such a block (to get compliant
1547 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1548 // reasons when pretty-printing. Also, unless an assignment (initialization)
1549 // is inside an initializer block, it is ignored.
1550 //
1551 // Create new block with one expected declaration.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001552 Block* block = new Block(NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001553 VariableProxy* last_var = NULL; // the last variable declared
1554 int nvars = 0; // the number of variables declared
1555 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001556 if (fni_ != NULL) fni_->Enter();
1557
Steve Blocka7e24c12009-10-30 11:49:00 +00001558 // Parse variable name.
1559 if (nvars > 0) Consume(Token::COMMA);
1560 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001561 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001562
Steve Block1e0659c2011-05-24 12:43:12 +01001563 // Strict mode variables may not be named eval or arguments
Steve Block44f0eee2011-05-26 01:26:41 +01001564 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01001565 ReportMessage("strict_var_name", Vector<const char*>::empty());
1566 *ok = false;
1567 return NULL;
1568 }
1569
Steve Blocka7e24c12009-10-30 11:49:00 +00001570 // Declare variable.
1571 // Note that we *always* must treat the initial value via a separate init
1572 // assignment for variables and constants because the value must be assigned
1573 // when the variable is encountered in the source. But the variable/constant
1574 // is declared (and set to 'undefined') upon entering the function within
1575 // which the variable or constant is declared. Only function variables have
1576 // an initial value in the declaration (because they are initialized upon
1577 // entering the function).
1578 //
1579 // If we have a const declaration, in an inner scope, the proxy is always
1580 // bound to the declared variable (independent of possibly surrounding with
1581 // statements).
1582 last_var = Declare(name, mode, NULL,
1583 is_const /* always bound for CONST! */,
1584 CHECK_OK);
1585 nvars++;
1586
1587 // Parse initialization expression if present and/or needed. A
1588 // declaration of the form:
1589 //
1590 // var v = x;
1591 //
1592 // is syntactic sugar for:
1593 //
1594 // var v; v = x;
1595 //
1596 // In particular, we need to re-lookup 'v' as it may be a
1597 // different 'v' than the 'v' in the declaration (if we are inside
1598 // a 'with' statement that makes a object property with name 'v'
1599 // visible).
1600 //
1601 // However, note that const declarations are different! A const
1602 // declaration of the form:
1603 //
1604 // const c = x;
1605 //
1606 // is *not* syntactic sugar for:
1607 //
1608 // const c; c = x;
1609 //
1610 // The "variable" c initialized to x is the same as the declared
1611 // one - there is no re-lookup (see the last parameter of the
1612 // Declare() call above).
1613
1614 Expression* value = NULL;
1615 int position = -1;
1616 if (peek() == Token::ASSIGN) {
1617 Expect(Token::ASSIGN, CHECK_OK);
1618 position = scanner().location().beg_pos;
1619 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001620 // Don't infer if it is "a = function(){...}();"-like expression.
1621 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer();
Steve Blocka7e24c12009-10-30 11:49:00 +00001622 }
1623
1624 // Make sure that 'const c' actually initializes 'c' to undefined
1625 // even though it seems like a stupid thing to do.
1626 if (value == NULL && is_const) {
1627 value = GetLiteralUndefined();
1628 }
1629
1630 // Global variable declarations must be compiled in a specific
1631 // way. When the script containing the global variable declaration
1632 // is entered, the global variable must be declared, so that if it
1633 // doesn't exist (not even in a prototype of the global object) it
1634 // gets created with an initial undefined value. This is handled
1635 // by the declarations part of the function representing the
1636 // top-level global code; see Runtime::DeclareGlobalVariable. If
1637 // it already exists (in the object or in a prototype), it is
1638 // *not* touched until the variable declaration statement is
1639 // executed.
1640 //
1641 // Executing the variable declaration statement will always
1642 // guarantee to give the global object a "local" variable; a
1643 // variable defined in the global object and not in any
1644 // prototype. This way, global variable declarations can shadow
1645 // properties in the prototype chain, but only after the variable
1646 // declaration statement has been executed. This is important in
1647 // browsers where the global object (window) has lots of
1648 // properties defined in prototype objects.
1649
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001650 if (top_scope_->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001651 // Compute the arguments for the runtime call.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001652 ZoneList<Expression*>* arguments = new ZoneList<Expression*>(3);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001653 arguments->Add(new Literal(name)); // we have at least 1 parameter
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001654 CallRuntime* initialize;
1655
1656 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001657 arguments->Add(value);
1658 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001659
1660 // Construct the call to Runtime_InitializeConstGlobal
1661 // and add it to the initialization statement block.
1662 // Note that the function does different things depending on
1663 // the number of arguments (1 or 2).
Steve Blocka7e24c12009-10-30 11:49:00 +00001664 initialize =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001665 new CallRuntime(
Steve Block44f0eee2011-05-26 01:26:41 +01001666 isolate()->factory()->InitializeConstGlobal_symbol(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001667 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1668 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001669 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001670 // Add strict mode.
1671 // We may want to pass singleton to avoid Literal allocations.
1672 arguments->Add(NewNumberLiteral(
Steve Block44f0eee2011-05-26 01:26:41 +01001673 top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001674
1675 // Be careful not to assign a value to the global variable if
1676 // we're in a with. The initialization value should not
1677 // necessarily be stored in the global object in that case,
1678 // which is why we need to generate a separate assignment node.
1679 if (value != NULL && !inside_with()) {
1680 arguments->Add(value);
1681 value = NULL; // zap the value to avoid the unnecessary assignment
1682 }
1683
1684 // Construct the call to Runtime_InitializeVarGlobal
1685 // and add it to the initialization statement block.
1686 // Note that the function does different things depending on
1687 // the number of arguments (2 or 3).
Steve Blocka7e24c12009-10-30 11:49:00 +00001688 initialize =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001689 new CallRuntime(
Steve Block44f0eee2011-05-26 01:26:41 +01001690 isolate()->factory()->InitializeVarGlobal_symbol(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001691 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1692 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001693 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001694
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001695 block->AddStatement(new ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001696 }
1697
1698 // Add an assignment node to the initialization statement block if
1699 // we still have a pending initialization value. We must distinguish
1700 // between variables and constants: Variable initializations are simply
1701 // assignments (with all the consequences if they are inside a 'with'
1702 // statement - they may change a 'with' object property). Constant
1703 // initializations always assign to the declared constant which is
1704 // always at the function scope level. This is only relevant for
1705 // dynamically looked-up variables and constants (the start context
1706 // for constant lookups is always the function context, while it is
1707 // the top context for variables). Sigh...
1708 if (value != NULL) {
1709 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001710 Assignment* assignment = new Assignment(op, last_var, value, position);
1711 if (block) block->AddStatement(new ExpressionStatement(assignment));
Steve Blocka7e24c12009-10-30 11:49:00 +00001712 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001713
1714 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001715 } while (peek() == Token::COMMA);
1716
1717 if (!is_const && nvars == 1) {
1718 // We have a single, non-const variable.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001719 ASSERT(last_var != NULL);
1720 *var = last_var;
Steve Blocka7e24c12009-10-30 11:49:00 +00001721 }
1722
1723 return block;
1724}
1725
1726
1727static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1728 ASSERT(!label.is_null());
1729 if (labels != NULL)
1730 for (int i = labels->length(); i-- > 0; )
1731 if (labels->at(i).is_identical_to(label))
1732 return true;
1733
1734 return false;
1735}
1736
1737
1738Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1739 bool* ok) {
1740 // ExpressionStatement | LabelledStatement ::
1741 // Expression ';'
1742 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001743 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001744 Expression* expr = ParseExpression(true, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001745 if (peek() == Token::COLON && starts_with_idenfifier && expr &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001746 expr->AsVariableProxy() != NULL &&
1747 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001748 // Expression is a single identifier, and not, e.g., a parenthesized
1749 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001750 VariableProxy* var = expr->AsVariableProxy();
1751 Handle<String> label = var->name();
1752 // TODO(1240780): We don't check for redeclaration of labels
1753 // during preparsing since keeping track of the set of active
1754 // labels requires nontrivial changes to the way scopes are
1755 // structured. However, these are probably changes we want to
1756 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001757 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1758 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1759 const char* elms[2] = { "Label", *c_string };
1760 Vector<const char*> args(elms, 2);
1761 ReportMessage("redeclaration", args);
1762 *ok = false;
1763 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001764 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001765 if (labels == NULL) labels = new ZoneStringList(4);
1766 labels->Add(label);
1767 // Remove the "ghost" variable that turned out to be a label
1768 // from the top scope. This way, we don't try to resolve it
1769 // during the scope processing.
1770 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001771 Expect(Token::COLON, CHECK_OK);
1772 return ParseStatement(labels, ok);
1773 }
1774
1775 // Parsed expression statement.
1776 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001777 return new ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001778}
1779
1780
1781IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1782 // IfStatement ::
1783 // 'if' '(' Expression ')' Statement ('else' Statement)?
1784
1785 Expect(Token::IF, CHECK_OK);
1786 Expect(Token::LPAREN, CHECK_OK);
1787 Expression* condition = ParseExpression(true, CHECK_OK);
1788 Expect(Token::RPAREN, CHECK_OK);
1789 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1790 Statement* else_statement = NULL;
1791 if (peek() == Token::ELSE) {
1792 Next();
1793 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001794 } else {
1795 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001796 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001797 return new IfStatement(condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001798}
1799
1800
1801Statement* Parser::ParseContinueStatement(bool* ok) {
1802 // ContinueStatement ::
1803 // 'continue' Identifier? ';'
1804
1805 Expect(Token::CONTINUE, CHECK_OK);
1806 Handle<String> label = Handle<String>::null();
1807 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001808 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001809 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1810 label = ParseIdentifier(CHECK_OK);
1811 }
1812 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001813 target = LookupContinueTarget(label, CHECK_OK);
1814 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001815 // Illegal continue statement.
1816 const char* message = "illegal_continue";
1817 Vector<Handle<String> > args;
1818 if (!label.is_null()) {
1819 message = "unknown_label";
1820 args = Vector<Handle<String> >(&label, 1);
1821 }
1822 ReportMessageAt(scanner().location(), message, args);
1823 *ok = false;
1824 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001825 }
1826 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001827 return new ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001828}
1829
1830
1831Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1832 // BreakStatement ::
1833 // 'break' Identifier? ';'
1834
1835 Expect(Token::BREAK, CHECK_OK);
1836 Handle<String> label;
1837 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001838 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001839 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1840 label = ParseIdentifier(CHECK_OK);
1841 }
1842 // Parse labeled break statements that target themselves into
1843 // empty statements, e.g. 'l1: l2: l3: break l2;'
1844 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001845 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001846 }
1847 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001848 target = LookupBreakTarget(label, CHECK_OK);
1849 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001850 // Illegal break statement.
1851 const char* message = "illegal_break";
1852 Vector<Handle<String> > args;
1853 if (!label.is_null()) {
1854 message = "unknown_label";
1855 args = Vector<Handle<String> >(&label, 1);
1856 }
1857 ReportMessageAt(scanner().location(), message, args);
1858 *ok = false;
1859 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001860 }
1861 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001862 return new BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001863}
1864
1865
1866Statement* Parser::ParseReturnStatement(bool* ok) {
1867 // ReturnStatement ::
1868 // 'return' Expression? ';'
1869
1870 // Consume the return token. It is necessary to do the before
1871 // reporting any errors on it, because of the way errors are
1872 // reported (underlining).
1873 Expect(Token::RETURN, CHECK_OK);
1874
1875 // An ECMAScript program is considered syntactically incorrect if it
1876 // contains a return statement that is not within the body of a
1877 // function. See ECMA-262, section 12.9, page 67.
1878 //
1879 // To be consistent with KJS we report the syntax error at runtime.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001880 if (!top_scope_->is_function_scope()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001881 Handle<String> type = isolate()->factory()->illegal_return_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00001882 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001883 return new ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001884 }
1885
1886 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001887 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001888 tok == Token::SEMICOLON ||
1889 tok == Token::RBRACE ||
1890 tok == Token::EOS) {
1891 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001892 return new ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001893 }
1894
1895 Expression* expr = ParseExpression(true, CHECK_OK);
1896 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001897 return new ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001898}
1899
1900
1901Block* Parser::WithHelper(Expression* obj,
1902 ZoneStringList* labels,
1903 bool is_catch_block,
1904 bool* ok) {
1905 // Parse the statement and collect escaping labels.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001906 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001907 TargetCollector collector(target_list);
1908 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001909 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001910 with_nesting_level_++;
1911 top_scope_->RecordWithStatement();
1912 stat = ParseStatement(labels, CHECK_OK);
1913 with_nesting_level_--;
1914 }
1915 // Create resulting block with two statements.
1916 // 1: Evaluate the with expression.
1917 // 2: The try-finally block evaluating the body.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001918 Block* result = new Block(NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001919
1920 if (result != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001921 result->AddStatement(new WithEnterStatement(obj, is_catch_block));
Steve Blocka7e24c12009-10-30 11:49:00 +00001922
1923 // Create body block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001924 Block* body = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001925 body->AddStatement(stat);
1926
1927 // Create exit block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001928 Block* exit = new Block(NULL, 1, false);
1929 exit->AddStatement(new WithExitStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00001930
1931 // Return a try-finally statement.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001932 TryFinallyStatement* wrapper = new TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001933 wrapper->set_escaping_targets(collector.targets());
1934 result->AddStatement(wrapper);
1935 }
1936 return result;
1937}
1938
1939
1940Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
1941 // WithStatement ::
1942 // 'with' '(' Expression ')' Statement
1943
1944 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001945
Steve Block44f0eee2011-05-26 01:26:41 +01001946 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001947 ReportMessage("strict_mode_with", Vector<const char*>::empty());
1948 *ok = false;
1949 return NULL;
1950 }
1951
Steve Blocka7e24c12009-10-30 11:49:00 +00001952 Expect(Token::LPAREN, CHECK_OK);
1953 Expression* expr = ParseExpression(true, CHECK_OK);
1954 Expect(Token::RPAREN, CHECK_OK);
1955
1956 return WithHelper(expr, labels, false, CHECK_OK);
1957}
1958
1959
1960CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1961 // CaseClause ::
1962 // 'case' Expression ':' Statement*
1963 // 'default' ':' Statement*
1964
1965 Expression* label = NULL; // NULL expression indicates default case
1966 if (peek() == Token::CASE) {
1967 Expect(Token::CASE, CHECK_OK);
1968 label = ParseExpression(true, CHECK_OK);
1969 } else {
1970 Expect(Token::DEFAULT, CHECK_OK);
1971 if (*default_seen_ptr) {
1972 ReportMessage("multiple_defaults_in_switch",
1973 Vector<const char*>::empty());
1974 *ok = false;
1975 return NULL;
1976 }
1977 *default_seen_ptr = true;
1978 }
1979 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001980 int pos = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001981 ZoneList<Statement*>* statements = new ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001982 while (peek() != Token::CASE &&
1983 peek() != Token::DEFAULT &&
1984 peek() != Token::RBRACE) {
1985 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001986 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001987 }
1988
Ben Murdochb0fe1622011-05-05 13:52:32 +01001989 return new CaseClause(label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001990}
1991
1992
1993SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
1994 bool* ok) {
1995 // SwitchStatement ::
1996 // 'switch' '(' Expression ')' '{' CaseClause* '}'
1997
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001998 SwitchStatement* statement = new SwitchStatement(labels);
1999 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002000
2001 Expect(Token::SWITCH, CHECK_OK);
2002 Expect(Token::LPAREN, CHECK_OK);
2003 Expression* tag = ParseExpression(true, CHECK_OK);
2004 Expect(Token::RPAREN, CHECK_OK);
2005
2006 bool default_seen = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002007 ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002008 Expect(Token::LBRACE, CHECK_OK);
2009 while (peek() != Token::RBRACE) {
2010 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002011 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002012 }
2013 Expect(Token::RBRACE, CHECK_OK);
2014
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002015 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002016 return statement;
2017}
2018
2019
2020Statement* Parser::ParseThrowStatement(bool* ok) {
2021 // ThrowStatement ::
2022 // 'throw' Expression ';'
2023
2024 Expect(Token::THROW, CHECK_OK);
2025 int pos = scanner().location().beg_pos;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002026 if (scanner().has_line_terminator_before_next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002027 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2028 *ok = false;
2029 return NULL;
2030 }
2031 Expression* exception = ParseExpression(true, CHECK_OK);
2032 ExpectSemicolon(CHECK_OK);
2033
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002034 return new ExpressionStatement(new Throw(exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002035}
2036
2037
2038TryStatement* Parser::ParseTryStatement(bool* ok) {
2039 // TryStatement ::
2040 // 'try' Block Catch
2041 // 'try' Block Finally
2042 // 'try' Block Catch Finally
2043 //
2044 // Catch ::
2045 // 'catch' '(' Identifier ')' Block
2046 //
2047 // Finally ::
2048 // 'finally' Block
2049
2050 Expect(Token::TRY, CHECK_OK);
2051
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002052 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002053 TargetCollector collector(target_list);
2054 Block* try_block;
2055
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002056 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002057 try_block = ParseBlock(NULL, CHECK_OK);
2058 }
2059
2060 Block* catch_block = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002061 Variable* catch_var = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002062 Block* finally_block = NULL;
2063
2064 Token::Value tok = peek();
2065 if (tok != Token::CATCH && tok != Token::FINALLY) {
2066 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2067 *ok = false;
2068 return NULL;
2069 }
2070
2071 // If we can break out from the catch block and there is a finally block,
2072 // then we will need to collect jump targets from the catch block. Since
2073 // we don't know yet if there will be a finally block, we always collect
2074 // the jump targets.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002075 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002076 TargetCollector catch_collector(catch_target_list);
2077 bool has_catch = false;
2078 if (tok == Token::CATCH) {
2079 has_catch = true;
2080 Consume(Token::CATCH);
2081
2082 Expect(Token::LPAREN, CHECK_OK);
2083 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002084
Steve Block44f0eee2011-05-26 01:26:41 +01002085 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01002086 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2087 *ok = false;
2088 return NULL;
2089 }
2090
Steve Blocka7e24c12009-10-30 11:49:00 +00002091 Expect(Token::RPAREN, CHECK_OK);
2092
2093 if (peek() == Token::LBRACE) {
2094 // Allocate a temporary for holding the finally state while
2095 // executing the finally block.
Steve Block44f0eee2011-05-26 01:26:41 +01002096 catch_var =
2097 top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002098 Literal* name_literal = new Literal(name);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002099 VariableProxy* catch_var_use = new VariableProxy(catch_var);
2100 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002101 { Target target(&this->target_stack_, &catch_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002102 catch_block = WithHelper(obj, NULL, true, CHECK_OK);
2103 }
2104 } else {
2105 Expect(Token::LBRACE, CHECK_OK);
2106 }
2107
2108 tok = peek();
2109 }
2110
2111 if (tok == Token::FINALLY || !has_catch) {
2112 Consume(Token::FINALLY);
2113 // Declare a variable for holding the finally state while
2114 // executing the finally block.
2115 finally_block = ParseBlock(NULL, CHECK_OK);
2116 }
2117
2118 // Simplify the AST nodes by converting:
2119 // 'try { } catch { } finally { }'
2120 // to:
2121 // 'try { try { } catch { } } finally { }'
2122
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002123 if (catch_block != NULL && finally_block != NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002124 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
Steve Block3ce2e202009-11-05 08:53:23 +00002125 TryCatchStatement* statement =
Ben Murdochb0fe1622011-05-05 13:52:32 +01002126 new TryCatchStatement(try_block, catch_var_defn, catch_block);
Steve Blocka7e24c12009-10-30 11:49:00 +00002127 statement->set_escaping_targets(collector.targets());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002128 try_block = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002129 try_block->AddStatement(statement);
2130 catch_block = NULL;
2131 }
2132
2133 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002134 if (catch_block != NULL) {
2135 ASSERT(finally_block == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002136 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
2137 result = new TryCatchStatement(try_block, catch_var_defn, catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002138 result->set_escaping_targets(collector.targets());
2139 } else {
2140 ASSERT(finally_block != NULL);
2141 result = new TryFinallyStatement(try_block, finally_block);
2142 // Add the jump targets of the try block and the catch block.
2143 for (int i = 0; i < collector.targets()->length(); i++) {
2144 catch_collector.AddTarget(collector.targets()->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002145 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002146 result->set_escaping_targets(catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002147 }
2148
2149 return result;
2150}
2151
2152
Steve Block3ce2e202009-11-05 08:53:23 +00002153DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2154 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002155 // DoStatement ::
2156 // 'do' Statement 'while' '(' Expression ')' ';'
2157
Steve Block44f0eee2011-05-26 01:26:41 +01002158 lexical_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002159 DoWhileStatement* loop = new DoWhileStatement(labels);
2160 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002161
2162 Expect(Token::DO, CHECK_OK);
2163 Statement* body = ParseStatement(NULL, CHECK_OK);
2164 Expect(Token::WHILE, CHECK_OK);
2165 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002166
2167 if (loop != NULL) {
2168 int position = scanner().location().beg_pos;
2169 loop->set_condition_position(position);
2170 }
2171
Steve Blocka7e24c12009-10-30 11:49:00 +00002172 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002173 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002174 Expect(Token::RPAREN, CHECK_OK);
2175
2176 // Allow do-statements to be terminated with and without
2177 // semi-colons. This allows code such as 'do;while(0)return' to
2178 // parse, which would not be the case if we had used the
2179 // ExpectSemicolon() functionality here.
2180 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2181
Steve Block3ce2e202009-11-05 08:53:23 +00002182 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002183 return loop;
2184}
2185
2186
Steve Block3ce2e202009-11-05 08:53:23 +00002187WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 // WhileStatement ::
2189 // 'while' '(' Expression ')' Statement
2190
Steve Block44f0eee2011-05-26 01:26:41 +01002191 lexical_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002192 WhileStatement* loop = new WhileStatement(labels);
2193 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);
Steve Block6ded16b2010-05-10 14:33:55 +01002198 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002199 Expect(Token::RPAREN, CHECK_OK);
2200 Statement* body = ParseStatement(NULL, CHECK_OK);
2201
Steve Block3ce2e202009-11-05 08:53:23 +00002202 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002203 return loop;
2204}
2205
2206
2207Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2208 // ForStatement ::
2209 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2210
Steve Block44f0eee2011-05-26 01:26:41 +01002211 lexical_scope_->AddLoop();
Steve Blocka7e24c12009-10-30 11:49:00 +00002212 Statement* init = NULL;
2213
2214 Expect(Token::FOR, CHECK_OK);
2215 Expect(Token::LPAREN, CHECK_OK);
2216 if (peek() != Token::SEMICOLON) {
2217 if (peek() == Token::VAR || peek() == Token::CONST) {
2218 Expression* each = NULL;
2219 Block* variable_statement =
2220 ParseVariableDeclarations(false, &each, CHECK_OK);
2221 if (peek() == Token::IN && each != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002222 ForInStatement* loop = new ForInStatement(labels);
2223 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002224
2225 Expect(Token::IN, CHECK_OK);
2226 Expression* enumerable = ParseExpression(true, CHECK_OK);
2227 Expect(Token::RPAREN, CHECK_OK);
2228
2229 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002230 loop->Initialize(each, enumerable, body);
2231 Block* result = new Block(NULL, 2, false);
2232 result->AddStatement(variable_statement);
2233 result->AddStatement(loop);
2234 // Parsed for-in loop w/ variable/const declaration.
2235 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002236 } else {
2237 init = variable_statement;
2238 }
2239
2240 } else {
2241 Expression* expression = ParseExpression(false, CHECK_OK);
2242 if (peek() == Token::IN) {
2243 // Signal a reference error if the expression is an invalid
2244 // left-hand side expression. We could report this as a syntax
2245 // error here but for compatibility with JSC we choose to report
2246 // the error at runtime.
2247 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002248 Handle<String> type =
2249 isolate()->factory()->invalid_lhs_in_for_in_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002250 expression = NewThrowReferenceError(type);
2251 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002252 ForInStatement* loop = new ForInStatement(labels);
2253 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002254
2255 Expect(Token::IN, CHECK_OK);
2256 Expression* enumerable = ParseExpression(true, CHECK_OK);
2257 Expect(Token::RPAREN, CHECK_OK);
2258
2259 Statement* body = ParseStatement(NULL, CHECK_OK);
2260 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002261 // Parsed for-in loop.
2262 return loop;
2263
2264 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002265 init = new ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002266 }
2267 }
2268 }
2269
2270 // Standard 'for' loop
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002271 ForStatement* loop = new ForStatement(labels);
2272 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002273
2274 // Parsed initializer at this point.
2275 Expect(Token::SEMICOLON, CHECK_OK);
2276
2277 Expression* cond = NULL;
2278 if (peek() != Token::SEMICOLON) {
2279 cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002280 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002281 }
2282 Expect(Token::SEMICOLON, CHECK_OK);
2283
2284 Statement* next = NULL;
2285 if (peek() != Token::RPAREN) {
2286 Expression* exp = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002287 next = new ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002288 }
2289 Expect(Token::RPAREN, CHECK_OK);
2290
2291 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002292 if (loop) loop->Initialize(init, cond, next, body);
2293 return loop;
2294}
2295
2296
2297// Precedence = 1
2298Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2299 // Expression ::
2300 // AssignmentExpression
2301 // Expression ',' AssignmentExpression
2302
2303 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2304 while (peek() == Token::COMMA) {
2305 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002306 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002307 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002308 result = new BinaryOperation(Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002309 }
2310 return result;
2311}
2312
2313
2314// Precedence = 2
2315Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2316 // AssignmentExpression ::
2317 // ConditionalExpression
2318 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2319
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002320 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002321 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2322
2323 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002324 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002325 // Parsed conditional expression only (no assignment).
2326 return expression;
2327 }
2328
2329 // Signal a reference error if the expression is an invalid left-hand
2330 // side expression. We could report this as a syntax error here but
2331 // for compatibility with JSC we choose to report the error at
2332 // runtime.
2333 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002334 Handle<String> type =
2335 isolate()->factory()->invalid_lhs_in_assignment_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002336 expression = NewThrowReferenceError(type);
2337 }
2338
Steve Block44f0eee2011-05-26 01:26:41 +01002339 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002340 // Assignment to eval or arguments is disallowed in strict mode.
2341 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2342 }
2343
Steve Blocka7e24c12009-10-30 11:49:00 +00002344 Token::Value op = Next(); // Get assignment operator.
2345 int pos = scanner().location().beg_pos;
2346 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2347
2348 // TODO(1231235): We try to estimate the set of properties set by
2349 // constructors. We define a new property whenever there is an
2350 // assignment to a property of 'this'. We should probably only add
2351 // properties if we haven't seen them before. Otherwise we'll
2352 // probably overestimate the number of properties.
2353 Property* property = expression ? expression->AsProperty() : NULL;
2354 if (op == Token::ASSIGN &&
2355 property != NULL &&
2356 property->obj()->AsVariableProxy() != NULL &&
2357 property->obj()->AsVariableProxy()->is_this()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002358 lexical_scope_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002359 }
2360
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002361 // If we assign a function literal to a property we pretenure the
2362 // literal so it can be added as a constant function property.
2363 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2364 right->AsFunctionLiteral()->set_pretenure(true);
2365 }
2366
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002367 if (fni_ != NULL) {
2368 // Check if the right hand side is a call to avoid inferring a
2369 // name if we're dealing with "a = function(){...}();"-like
2370 // expression.
2371 if ((op == Token::INIT_VAR
2372 || op == Token::INIT_CONST
2373 || op == Token::ASSIGN)
2374 && (right->AsCall() == NULL)) {
2375 fni_->Infer();
2376 }
2377 fni_->Leave();
2378 }
2379
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002380 return new Assignment(op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002381}
2382
2383
2384// Precedence = 3
2385Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2386 // ConditionalExpression ::
2387 // LogicalOrExpression
2388 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2389
2390 // We start using the binary expression parser for prec >= 4 only!
2391 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2392 if (peek() != Token::CONDITIONAL) return expression;
2393 Consume(Token::CONDITIONAL);
2394 // In parsing the first assignment expression in conditional
2395 // expressions we always accept the 'in' keyword; see ECMA-262,
2396 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002397 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002398 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2399 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002400 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002401 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002402 return new Conditional(expression, left, right,
2403 left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002404}
2405
2406
2407static int Precedence(Token::Value tok, bool accept_IN) {
2408 if (tok == Token::IN && !accept_IN)
2409 return 0; // 0 precedence will terminate binary expression parsing
2410
2411 return Token::Precedence(tok);
2412}
2413
2414
2415// Precedence >= 4
2416Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2417 ASSERT(prec >= 4);
2418 Expression* x = ParseUnaryExpression(CHECK_OK);
2419 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2420 // prec1 >= 4
2421 while (Precedence(peek(), accept_IN) == prec1) {
2422 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002423 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002424 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2425
2426 // Compute some expressions involving only number literals.
2427 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2428 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2429 double x_val = x->AsLiteral()->handle()->Number();
2430 double y_val = y->AsLiteral()->handle()->Number();
2431
2432 switch (op) {
2433 case Token::ADD:
2434 x = NewNumberLiteral(x_val + y_val);
2435 continue;
2436 case Token::SUB:
2437 x = NewNumberLiteral(x_val - y_val);
2438 continue;
2439 case Token::MUL:
2440 x = NewNumberLiteral(x_val * y_val);
2441 continue;
2442 case Token::DIV:
2443 x = NewNumberLiteral(x_val / y_val);
2444 continue;
2445 case Token::BIT_OR:
2446 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2447 continue;
2448 case Token::BIT_AND:
2449 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2450 continue;
2451 case Token::BIT_XOR:
2452 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2453 continue;
2454 case Token::SHL: {
2455 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2456 x = NewNumberLiteral(value);
2457 continue;
2458 }
2459 case Token::SHR: {
2460 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2461 uint32_t value = DoubleToUint32(x_val) >> shift;
2462 x = NewNumberLiteral(value);
2463 continue;
2464 }
2465 case Token::SAR: {
2466 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2467 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2468 x = NewNumberLiteral(value);
2469 continue;
2470 }
2471 default:
2472 break;
2473 }
2474 }
2475
Steve Blocka7e24c12009-10-30 11:49:00 +00002476 // For now we distinguish between comparisons and other binary
2477 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002478 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002479 if (Token::IsCompareOp(op)) {
2480 // We have a comparison.
2481 Token::Value cmp = op;
2482 switch (op) {
2483 case Token::NE: cmp = Token::EQ; break;
2484 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2485 default: break;
2486 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002487 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002488 if (cmp != op) {
2489 // The comparison was negated - add a NOT.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002490 x = new UnaryOperation(Token::NOT, x);
Steve Blocka7e24c12009-10-30 11:49:00 +00002491 }
2492
2493 } else {
2494 // We have a "normal" binary operation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002495 x = new BinaryOperation(op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002496 }
2497 }
2498 }
2499 return x;
2500}
2501
2502
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002503Expression* Parser::NewCompareNode(Token::Value op,
2504 Expression* x,
2505 Expression* y,
2506 int position) {
2507 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002508 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002509 bool is_strict = (op == Token::EQ_STRICT);
2510 Literal* x_literal = x->AsLiteral();
2511 if (x_literal != NULL && x_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002512 return new CompareToNull(is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002513 }
2514
2515 Literal* y_literal = y->AsLiteral();
2516 if (y_literal != NULL && y_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002517 return new CompareToNull(is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002518 }
2519 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002520 return new CompareOperation(op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002521}
2522
2523
Steve Blocka7e24c12009-10-30 11:49:00 +00002524Expression* Parser::ParseUnaryExpression(bool* ok) {
2525 // UnaryExpression ::
2526 // PostfixExpression
2527 // 'delete' UnaryExpression
2528 // 'void' UnaryExpression
2529 // 'typeof' UnaryExpression
2530 // '++' UnaryExpression
2531 // '--' UnaryExpression
2532 // '+' UnaryExpression
2533 // '-' UnaryExpression
2534 // '~' UnaryExpression
2535 // '!' UnaryExpression
2536
2537 Token::Value op = peek();
2538 if (Token::IsUnaryOp(op)) {
2539 op = Next();
2540 Expression* expression = ParseUnaryExpression(CHECK_OK);
2541
2542 // Compute some expressions involving only number literals.
2543 if (expression != NULL && expression->AsLiteral() &&
2544 expression->AsLiteral()->handle()->IsNumber()) {
2545 double value = expression->AsLiteral()->handle()->Number();
2546 switch (op) {
2547 case Token::ADD:
2548 return expression;
2549 case Token::SUB:
2550 return NewNumberLiteral(-value);
2551 case Token::BIT_NOT:
2552 return NewNumberLiteral(~DoubleToInt32(value));
2553 default: break;
2554 }
2555 }
2556
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002557 // "delete identifier" is a syntax error in strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01002558 if (op == Token::DELETE && top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002559 VariableProxy* operand = expression->AsVariableProxy();
2560 if (operand != NULL && !operand->is_this()) {
2561 ReportMessage("strict_delete", Vector<const char*>::empty());
2562 *ok = false;
2563 return NULL;
2564 }
2565 }
2566
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002567 return new UnaryOperation(op, expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002568
2569 } else if (Token::IsCountOp(op)) {
2570 op = Next();
2571 Expression* expression = ParseUnaryExpression(CHECK_OK);
2572 // Signal a reference error if the expression is an invalid
2573 // left-hand side expression. We could report this as a syntax
2574 // error here but for compatibility with JSC we choose to report the
2575 // error at runtime.
2576 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002577 Handle<String> type =
2578 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002579 expression = NewThrowReferenceError(type);
2580 }
Steve Block1e0659c2011-05-24 12:43:12 +01002581
Steve Block44f0eee2011-05-26 01:26:41 +01002582 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002583 // Prefix expression operand in strict mode may not be eval or arguments.
2584 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2585 }
2586
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002587 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002588 IncrementOperation* increment = new IncrementOperation(op, expression);
2589 return new CountOperation(true /* prefix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002590
2591 } else {
2592 return ParsePostfixExpression(ok);
2593 }
2594}
2595
2596
2597Expression* Parser::ParsePostfixExpression(bool* ok) {
2598 // PostfixExpression ::
2599 // LeftHandSideExpression ('++' | '--')?
2600
2601 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002602 if (!scanner().has_line_terminator_before_next() &&
2603 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002604 // Signal a reference error if the expression is an invalid
2605 // left-hand side expression. We could report this as a syntax
2606 // error here but for compatibility with JSC we choose to report the
2607 // error at runtime.
2608 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002609 Handle<String> type =
2610 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002611 expression = NewThrowReferenceError(type);
2612 }
Steve Block1e0659c2011-05-24 12:43:12 +01002613
Steve Block44f0eee2011-05-26 01:26:41 +01002614 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002615 // Postfix expression operand in strict mode may not be eval or arguments.
2616 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2617 }
2618
Steve Blocka7e24c12009-10-30 11:49:00 +00002619 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002620 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002621 IncrementOperation* increment = new IncrementOperation(next, expression);
2622 expression = new CountOperation(false /* postfix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002623 }
2624 return expression;
2625}
2626
2627
2628Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2629 // LeftHandSideExpression ::
2630 // (NewExpression | MemberExpression) ...
2631
2632 Expression* result;
2633 if (peek() == Token::NEW) {
2634 result = ParseNewExpression(CHECK_OK);
2635 } else {
2636 result = ParseMemberExpression(CHECK_OK);
2637 }
2638
2639 while (true) {
2640 switch (peek()) {
2641 case Token::LBRACK: {
2642 Consume(Token::LBRACK);
2643 int pos = scanner().location().beg_pos;
2644 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002645 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002646 Expect(Token::RBRACK, CHECK_OK);
2647 break;
2648 }
2649
2650 case Token::LPAREN: {
2651 int pos = scanner().location().beg_pos;
2652 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2653
2654 // Keep track of eval() calls since they disable all local variable
2655 // optimizations.
2656 // The calls that need special treatment are the
2657 // direct (i.e. not aliased) eval calls. These calls are all of the
2658 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002659 // declared in the current scope chain.
2660 // These calls are marked as potentially direct eval calls. Whether
2661 // they are actually direct calls to eval is determined at run time.
2662 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2663 // in the local scope chain. It only matters that it's called "eval",
2664 // is called without a receiver and it refers to the original eval
2665 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002666 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01002667 if (callee != NULL &&
2668 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002669 Handle<String> name = callee->name();
2670 Variable* var = top_scope_->Lookup(name);
2671 if (var == NULL) {
2672 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002673 }
2674 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002675 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002676 break;
2677 }
2678
2679 case Token::PERIOD: {
2680 Consume(Token::PERIOD);
2681 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002682 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002683 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002684 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002685 break;
2686 }
2687
2688 default:
2689 return result;
2690 }
2691 }
2692}
2693
2694
Steve Blocka7e24c12009-10-30 11:49:00 +00002695Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2696 // NewExpression ::
2697 // ('new')+ MemberExpression
2698
2699 // The grammar for new expressions is pretty warped. The keyword
2700 // 'new' can either be a part of the new expression (where it isn't
2701 // followed by an argument list) or a part of the member expression,
2702 // where it must be followed by an argument list. To accommodate
2703 // this, we parse the 'new' keywords greedily and keep track of how
2704 // many we have parsed. This information is then passed on to the
2705 // member expression parser, which is only allowed to match argument
2706 // lists as long as it has 'new' prefixes left
2707 Expect(Token::NEW, CHECK_OK);
2708 PositionStack::Element pos(stack, scanner().location().beg_pos);
2709
2710 Expression* result;
2711 if (peek() == Token::NEW) {
2712 result = ParseNewPrefix(stack, CHECK_OK);
2713 } else {
2714 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2715 }
2716
2717 if (!stack->is_empty()) {
2718 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002719 result = new CallNew(result, new ZoneList<Expression*>(0), last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002720 }
2721 return result;
2722}
2723
2724
2725Expression* Parser::ParseNewExpression(bool* ok) {
2726 PositionStack stack(ok);
2727 return ParseNewPrefix(&stack, ok);
2728}
2729
2730
2731Expression* Parser::ParseMemberExpression(bool* ok) {
2732 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2733}
2734
2735
2736Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2737 bool* ok) {
2738 // MemberExpression ::
2739 // (PrimaryExpression | FunctionLiteral)
2740 // ('[' Expression ']' | '.' Identifier | Arguments)*
2741
2742 // Parse the initial primary or function expression.
2743 Expression* result = NULL;
2744 if (peek() == Token::FUNCTION) {
2745 Expect(Token::FUNCTION, CHECK_OK);
2746 int function_token_position = scanner().location().beg_pos;
2747 Handle<String> name;
Steve Block1e0659c2011-05-24 12:43:12 +01002748 bool is_reserved_name = false;
2749 if (peek_any_identifier()) {
2750 name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK);
2751 }
2752 result = ParseFunctionLiteral(name, is_reserved_name,
2753 function_token_position, NESTED, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002754 } else {
2755 result = ParsePrimaryExpression(CHECK_OK);
2756 }
2757
2758 while (true) {
2759 switch (peek()) {
2760 case Token::LBRACK: {
2761 Consume(Token::LBRACK);
2762 int pos = scanner().location().beg_pos;
2763 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002764 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002765 Expect(Token::RBRACK, CHECK_OK);
2766 break;
2767 }
2768 case Token::PERIOD: {
2769 Consume(Token::PERIOD);
2770 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002771 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002772 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002773 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002774 break;
2775 }
2776 case Token::LPAREN: {
2777 if ((stack == NULL) || stack->is_empty()) return result;
2778 // Consume one of the new prefixes (already parsed).
2779 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2780 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002781 result = new CallNew(result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002782 break;
2783 }
2784 default:
2785 return result;
2786 }
2787 }
2788}
2789
2790
2791DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2792 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2793 // contexts this is used as a statement which invokes the debugger as i a
2794 // break point is present.
2795 // DebuggerStatement ::
2796 // 'debugger' ';'
2797
2798 Expect(Token::DEBUGGER, CHECK_OK);
2799 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002800 return new DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002801}
2802
2803
2804void Parser::ReportUnexpectedToken(Token::Value token) {
2805 // We don't report stack overflows here, to avoid increasing the
2806 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002807 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002808 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002809 // Four of the tokens are treated specially
2810 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002811 case Token::EOS:
2812 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2813 case Token::NUMBER:
2814 return ReportMessage("unexpected_token_number",
2815 Vector<const char*>::empty());
2816 case Token::STRING:
2817 return ReportMessage("unexpected_token_string",
2818 Vector<const char*>::empty());
2819 case Token::IDENTIFIER:
2820 return ReportMessage("unexpected_token_identifier",
2821 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002822 case Token::FUTURE_RESERVED_WORD:
Steve Block44f0eee2011-05-26 01:26:41 +01002823 return ReportMessage(top_scope_->is_strict_mode() ?
Steve Block1e0659c2011-05-24 12:43:12 +01002824 "unexpected_strict_reserved" :
2825 "unexpected_token_identifier",
2826 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002827 default:
2828 const char* name = Token::String(token);
2829 ASSERT(name != NULL);
2830 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002831 }
2832}
2833
2834
Leon Clarkeac952652010-07-15 11:15:24 +01002835void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2836 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2837 const char* element[1] = { *name_string };
2838 ReportMessage("invalid_preparser_data",
2839 Vector<const char*>(element, 1));
2840 *ok = false;
2841}
2842
2843
Steve Blocka7e24c12009-10-30 11:49:00 +00002844Expression* Parser::ParsePrimaryExpression(bool* ok) {
2845 // PrimaryExpression ::
2846 // 'this'
2847 // 'null'
2848 // 'true'
2849 // 'false'
2850 // Identifier
2851 // Number
2852 // String
2853 // ArrayLiteral
2854 // ObjectLiteral
2855 // RegExpLiteral
2856 // '(' Expression ')'
2857
2858 Expression* result = NULL;
2859 switch (peek()) {
2860 case Token::THIS: {
2861 Consume(Token::THIS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002862 VariableProxy* recv = top_scope_->receiver();
2863 result = recv;
Steve Blocka7e24c12009-10-30 11:49:00 +00002864 break;
2865 }
2866
2867 case Token::NULL_LITERAL:
2868 Consume(Token::NULL_LITERAL);
Steve Block44f0eee2011-05-26 01:26:41 +01002869 result = new Literal(isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002870 break;
2871
2872 case Token::TRUE_LITERAL:
2873 Consume(Token::TRUE_LITERAL);
Steve Block44f0eee2011-05-26 01:26:41 +01002874 result = new Literal(isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002875 break;
2876
2877 case Token::FALSE_LITERAL:
2878 Consume(Token::FALSE_LITERAL);
Steve Block44f0eee2011-05-26 01:26:41 +01002879 result = new Literal(isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002880 break;
2881
Steve Block1e0659c2011-05-24 12:43:12 +01002882 case Token::IDENTIFIER:
2883 case Token::FUTURE_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00002884 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002885 if (fni_ != NULL) fni_->PushVariableName(name);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002886 result = top_scope_->NewUnresolved(name, inside_with());
Steve Blocka7e24c12009-10-30 11:49:00 +00002887 break;
2888 }
2889
2890 case Token::NUMBER: {
2891 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01002892 ASSERT(scanner().is_literal_ascii());
2893 double value = StringToDouble(scanner().literal_ascii_string(),
2894 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002895 result = NewNumberLiteral(value);
2896 break;
2897 }
2898
2899 case Token::STRING: {
2900 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01002901 Handle<String> symbol = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002902 result = new Literal(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002903 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002904 break;
2905 }
2906
2907 case Token::ASSIGN_DIV:
2908 result = ParseRegExpLiteral(true, CHECK_OK);
2909 break;
2910
2911 case Token::DIV:
2912 result = ParseRegExpLiteral(false, CHECK_OK);
2913 break;
2914
2915 case Token::LBRACK:
2916 result = ParseArrayLiteral(CHECK_OK);
2917 break;
2918
2919 case Token::LBRACE:
2920 result = ParseObjectLiteral(CHECK_OK);
2921 break;
2922
2923 case Token::LPAREN:
2924 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002925 // Heuristically try to detect immediately called functions before
2926 // seeing the call parentheses.
2927 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00002928 result = ParseExpression(true, CHECK_OK);
2929 Expect(Token::RPAREN, CHECK_OK);
2930 break;
2931
2932 case Token::MOD:
2933 if (allow_natives_syntax_ || extension_ != NULL) {
2934 result = ParseV8Intrinsic(CHECK_OK);
2935 break;
2936 }
2937 // If we're not allowing special syntax we fall-through to the
2938 // default case.
2939
2940 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01002941 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00002942 ReportUnexpectedToken(tok);
2943 *ok = false;
2944 return NULL;
2945 }
2946 }
2947
2948 return result;
2949}
2950
2951
Leon Clarke4515c472010-02-03 11:58:03 +00002952void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
2953 Handle<FixedArray> literals,
2954 bool* is_simple,
2955 int* depth) {
2956 // Fill in the literals.
2957 // Accumulate output values in local variables.
2958 bool is_simple_acc = true;
2959 int depth_acc = 1;
2960 for (int i = 0; i < values->length(); i++) {
2961 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
2962 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2963 depth_acc = m_literal->depth() + 1;
2964 }
2965 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
2966 if (boilerplate_value->IsUndefined()) {
2967 literals->set_the_hole(i);
2968 is_simple_acc = false;
2969 } else {
2970 literals->set(i, *boilerplate_value);
2971 }
2972 }
2973
2974 *is_simple = is_simple_acc;
2975 *depth = depth_acc;
2976}
2977
2978
Steve Blocka7e24c12009-10-30 11:49:00 +00002979Expression* Parser::ParseArrayLiteral(bool* ok) {
2980 // ArrayLiteral ::
2981 // '[' Expression? (',' Expression?)* ']'
2982
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002983 ZoneList<Expression*>* values = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002984 Expect(Token::LBRACK, CHECK_OK);
2985 while (peek() != Token::RBRACK) {
2986 Expression* elem;
2987 if (peek() == Token::COMMA) {
2988 elem = GetLiteralTheHole();
2989 } else {
2990 elem = ParseAssignmentExpression(true, CHECK_OK);
2991 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002992 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00002993 if (peek() != Token::RBRACK) {
2994 Expect(Token::COMMA, CHECK_OK);
2995 }
2996 }
2997 Expect(Token::RBRACK, CHECK_OK);
2998
2999 // Update the scope information before the pre-parsing bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003000 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003001
Steve Blocka7e24c12009-10-30 11:49:00 +00003002 // Allocate a fixed array with all the literals.
3003 Handle<FixedArray> literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003004 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003005
3006 // Fill in the literals.
3007 bool is_simple = true;
3008 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003009 for (int i = 0, n = values->length(); i < n; i++) {
3010 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003011 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3012 depth = m_literal->depth() + 1;
3013 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003014 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003015 if (boilerplate_value->IsUndefined()) {
3016 literals->set_the_hole(i);
3017 is_simple = false;
3018 } else {
3019 literals->set(i, *boilerplate_value);
3020 }
3021 }
3022
Iain Merrick75681382010-08-19 15:07:18 +01003023 // Simple and shallow arrays can be lazily copied, we transform the
3024 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003025 if (is_simple && depth == 1 && values->length() > 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01003026 literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003027 }
3028
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003029 return new ArrayLiteral(literals, values,
3030 literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003031}
3032
3033
3034bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3035 return property != NULL &&
3036 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3037}
3038
3039
3040bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003041 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003042 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3043 return lit != NULL && lit->is_simple();
3044}
3045
Iain Merrick75681382010-08-19 15:07:18 +01003046
3047bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3048 Expression* value) {
3049 // If value is a literal the property value is already set in the
3050 // boilerplate object.
3051 if (value->AsLiteral() != NULL) return false;
3052 // If value is a materialized literal the property value is already set
3053 // in the boilerplate object if it is simple.
3054 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3055 return true;
3056}
3057
3058
Steve Blocka7e24c12009-10-30 11:49:00 +00003059Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3060 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003061 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003062 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3063 if (object_literal != NULL) {
3064 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003065 if (object_literal->fast_elements()) {
3066 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3067 } else {
3068 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3069 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003070 result->set(kElementsSlot, *object_literal->constant_properties());
3071 } else {
3072 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3073 ASSERT(array_literal != NULL && array_literal->is_simple());
3074 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003075 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003076 }
3077 return result;
3078}
3079
3080
3081CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3082 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3083 return static_cast<Type>(type_value->value());
3084}
3085
3086
3087Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3088 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3089}
3090
3091
3092Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3093 if (expression->AsLiteral() != NULL) {
3094 return expression->AsLiteral()->handle();
3095 }
3096 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3097 return CompileTimeValue::GetValue(expression);
3098 }
Steve Block44f0eee2011-05-26 01:26:41 +01003099 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003100}
3101
Steve Block1e0659c2011-05-24 12:43:12 +01003102// Defined in ast.cc
3103bool IsEqualString(void* first, void* second);
3104bool IsEqualNumber(void* first, void* second);
3105
3106
3107// Validation per 11.1.5 Object Initialiser
3108class ObjectLiteralPropertyChecker {
3109 public:
3110 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3111 props(&IsEqualString),
3112 elems(&IsEqualNumber),
3113 parser_(parser),
3114 strict_(strict) {
3115 }
3116
3117 void CheckProperty(
3118 ObjectLiteral::Property* property,
3119 Scanner::Location loc,
3120 bool* ok);
3121
3122 private:
3123 enum PropertyKind {
3124 kGetAccessor = 0x01,
3125 kSetAccessor = 0x02,
3126 kAccessor = kGetAccessor | kSetAccessor,
3127 kData = 0x04
3128 };
3129
3130 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3131 switch (property->kind()) {
3132 case ObjectLiteral::Property::GETTER:
3133 return kGetAccessor;
3134 case ObjectLiteral::Property::SETTER:
3135 return kSetAccessor;
3136 default:
3137 return kData;
3138 }
3139 }
3140
3141 HashMap props;
3142 HashMap elems;
3143 Parser* parser_;
3144 bool strict_;
3145};
3146
3147
3148void ObjectLiteralPropertyChecker::CheckProperty(
3149 ObjectLiteral::Property* property,
3150 Scanner::Location loc,
3151 bool* ok) {
3152
3153 ASSERT(property != NULL);
3154
3155 Literal *lit = property->key();
3156 Handle<Object> handle = lit->handle();
3157
3158 uint32_t hash;
3159 HashMap* map;
3160 void* key;
3161
3162 if (handle->IsSymbol()) {
3163 Handle<String> name(String::cast(*handle));
3164 if (name->AsArrayIndex(&hash)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003165 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
Steve Block1e0659c2011-05-24 12:43:12 +01003166 key = key_handle.location();
3167 map = &elems;
3168 } else {
3169 key = handle.location();
3170 hash = name->Hash();
3171 map = &props;
3172 }
3173 } else if (handle->ToArrayIndex(&hash)) {
3174 key = handle.location();
3175 map = &elems;
3176 } else {
3177 ASSERT(handle->IsNumber());
3178 double num = handle->Number();
3179 char arr[100];
3180 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3181 const char* str = DoubleToCString(num, buffer);
Steve Block44f0eee2011-05-26 01:26:41 +01003182 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
Steve Block1e0659c2011-05-24 12:43:12 +01003183 key = name.location();
3184 hash = name->Hash();
3185 map = &props;
3186 }
3187
3188 // Lookup property previously defined, if any.
3189 HashMap::Entry* entry = map->Lookup(key, hash, true);
3190 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3191 intptr_t curr = GetPropertyKind(property);
3192
3193 // Duplicate data properties are illegal in strict mode.
3194 if (strict_ && (curr & prev & kData) != 0) {
3195 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3196 Vector<const char*>::empty());
3197 *ok = false;
3198 return;
3199 }
3200 // Data property conflicting with an accessor.
3201 if (((curr & kData) && (prev & kAccessor)) ||
3202 ((prev & kData) && (curr & kAccessor))) {
3203 parser_->ReportMessageAt(loc, "accessor_data_property",
3204 Vector<const char*>::empty());
3205 *ok = false;
3206 return;
3207 }
3208 // Two accessors of the same type conflicting
3209 if ((curr & prev & kAccessor) != 0) {
3210 parser_->ReportMessageAt(loc, "accessor_get_set",
3211 Vector<const char*>::empty());
3212 *ok = false;
3213 return;
3214 }
3215
3216 // Update map
3217 entry->value = reinterpret_cast<void*> (prev | curr);
3218 *ok = true;
3219}
3220
Steve Blocka7e24c12009-10-30 11:49:00 +00003221
Leon Clarke4515c472010-02-03 11:58:03 +00003222void Parser::BuildObjectLiteralConstantProperties(
3223 ZoneList<ObjectLiteral::Property*>* properties,
3224 Handle<FixedArray> constant_properties,
3225 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003226 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003227 int* depth) {
3228 int position = 0;
3229 // Accumulate the value in local variables and store it at the end.
3230 bool is_simple_acc = true;
3231 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003232 uint32_t max_element_index = 0;
3233 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003234 for (int i = 0; i < properties->length(); i++) {
3235 ObjectLiteral::Property* property = properties->at(i);
3236 if (!IsBoilerplateProperty(property)) {
3237 is_simple_acc = false;
3238 continue;
3239 }
3240 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3241 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3242 depth_acc = m_literal->depth() + 1;
3243 }
3244
3245 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3246 // value for COMPUTED properties, the real value is filled in at
3247 // runtime. The enumeration order is maintained.
3248 Handle<Object> key = property->key()->handle();
3249 Handle<Object> value = GetBoilerplateValue(property->value());
3250 is_simple_acc = is_simple_acc && !value->IsUndefined();
3251
Steve Block6ded16b2010-05-10 14:33:55 +01003252 // Keep track of the number of elements in the object literal and
3253 // the largest element index. If the largest element index is
3254 // much larger than the number of elements, creating an object
3255 // literal with fast elements will be a waste of space.
3256 uint32_t element_index = 0;
3257 if (key->IsString()
3258 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3259 && element_index > max_element_index) {
3260 max_element_index = element_index;
3261 elements++;
3262 } else if (key->IsSmi()) {
3263 int key_value = Smi::cast(*key)->value();
3264 if (key_value > 0
3265 && static_cast<uint32_t>(key_value) > max_element_index) {
3266 max_element_index = key_value;
3267 }
3268 elements++;
3269 }
3270
Leon Clarke4515c472010-02-03 11:58:03 +00003271 // Add name, value pair to the fixed array.
3272 constant_properties->set(position++, *key);
3273 constant_properties->set(position++, *value);
3274 }
Steve Block6ded16b2010-05-10 14:33:55 +01003275 *fast_elements =
3276 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003277 *is_simple = is_simple_acc;
3278 *depth = depth_acc;
3279}
3280
3281
Ben Murdochbb769b22010-08-11 14:56:33 +01003282ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3283 bool* ok) {
3284 // Special handling of getter and setter syntax:
3285 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3286 // We have already read the "get" or "set" keyword.
3287 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003288 bool is_keyword = Token::IsKeyword(next);
3289 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003290 next == Token::FUTURE_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003291 next == Token::STRING || is_keyword) {
3292 Handle<String> name;
3293 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003294 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003295 } else {
3296 name = GetSymbol(CHECK_OK);
3297 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003298 FunctionLiteral* value =
3299 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003300 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003301 RelocInfo::kNoPosition,
3302 DECLARATION,
3303 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003304 // Allow any number of parameters for compatiabilty with JSC.
3305 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003306 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003307 new ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003308 return property;
3309 } else {
3310 ReportUnexpectedToken(next);
3311 *ok = false;
3312 return NULL;
3313 }
3314}
3315
3316
Steve Blocka7e24c12009-10-30 11:49:00 +00003317Expression* Parser::ParseObjectLiteral(bool* ok) {
3318 // ObjectLiteral ::
3319 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003320 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3321 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003322 // )*[','] '}'
3323
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003324 ZoneList<ObjectLiteral::Property*>* properties =
3325 new ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003326 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003327 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003328
Steve Block44f0eee2011-05-26 01:26:41 +01003329 ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003330
Steve Blocka7e24c12009-10-30 11:49:00 +00003331 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003332 Scanner::Location loc = scanner().location();
3333
Steve Blocka7e24c12009-10-30 11:49:00 +00003334 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003335 if (fni_ != NULL) fni_->Enter();
3336
Steve Blocka7e24c12009-10-30 11:49:00 +00003337 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003338 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003339
3340 // Location of the property name token
3341 Scanner::Location loc = scanner().peek_location();
3342
Ben Murdochbb769b22010-08-11 14:56:33 +01003343 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003344 case Token::FUTURE_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003345 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003346 bool is_getter = false;
3347 bool is_setter = false;
3348 Handle<String> id =
3349 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003350 if (fni_ != NULL) fni_->PushLiteralName(id);
3351
Ben Murdochbb769b22010-08-11 14:56:33 +01003352 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003353 // Update loc to point to the identifier
3354 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003355 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003356 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3357 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003358 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003359 }
Steve Block1e0659c2011-05-24 12:43:12 +01003360 // Validate the property.
3361 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003362 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003363 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003364
3365 if (fni_ != NULL) {
3366 fni_->Infer();
3367 fni_->Leave();
3368 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003369 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003370 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003371 // Failed to parse as get/set property, so it's just a property
3372 // called "get" or "set".
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003373 key = new Literal(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003374 break;
3375 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003376 case Token::STRING: {
3377 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003378 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003379 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003380 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003381 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003382 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003383 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003384 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003385 key = new Literal(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003386 break;
3387 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003388 case Token::NUMBER: {
3389 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003390 ASSERT(scanner().is_literal_ascii());
3391 double value = StringToDouble(scanner().literal_ascii_string(),
3392 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003393 key = NewNumberLiteral(value);
3394 break;
3395 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003396 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003397 if (Token::IsKeyword(next)) {
3398 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003399 Handle<String> string = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003400 key = new Literal(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003401 } else {
3402 // Unexpected token.
3403 Token::Value next = Next();
3404 ReportUnexpectedToken(next);
3405 *ok = false;
3406 return NULL;
3407 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003408 }
3409
3410 Expect(Token::COLON, CHECK_OK);
3411 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3412
3413 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003414 new ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003415
Steve Block44f0eee2011-05-26 01:26:41 +01003416 // Mark object literals that contain function literals and pretenure the
3417 // literal so it can be added as a constant function property.
3418 if (value->AsFunctionLiteral() != NULL) {
3419 has_function = true;
3420 value->AsFunctionLiteral()->set_pretenure(true);
3421 }
3422
Steve Blocka7e24c12009-10-30 11:49:00 +00003423 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3424 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003425 // Validate the property
3426 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003427 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003428
3429 // TODO(1240767): Consider allowing trailing comma.
3430 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003431
3432 if (fni_ != NULL) {
3433 fni_->Infer();
3434 fni_->Leave();
3435 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003436 }
3437 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003438
Steve Blocka7e24c12009-10-30 11:49:00 +00003439 // Computation of literal_index must happen before pre parse bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003440 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003441
Steve Block44f0eee2011-05-26 01:26:41 +01003442 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3443 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003444
Steve Blocka7e24c12009-10-30 11:49:00 +00003445 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003446 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003447 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003448 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003449 constant_properties,
3450 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003451 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003452 &depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003453 return new ObjectLiteral(constant_properties,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003454 properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003455 literal_index,
3456 is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003457 fast_elements,
Steve Block44f0eee2011-05-26 01:26:41 +01003458 depth,
3459 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003460}
3461
3462
3463Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003464 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003465 Next();
3466 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3467 *ok = false;
3468 return NULL;
3469 }
3470
Steve Block44f0eee2011-05-26 01:26:41 +01003471 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003472
Steve Block9fac8402011-05-12 15:51:54 +01003473 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003474 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003475 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003476 Next();
3477
3478 return new RegExpLiteral(js_pattern, js_flags, literal_index);
3479}
3480
3481
3482ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3483 // Arguments ::
3484 // '(' (AssignmentExpression)*[','] ')'
3485
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003486 ZoneList<Expression*>* result = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003487 Expect(Token::LPAREN, CHECK_OK);
3488 bool done = (peek() == Token::RPAREN);
3489 while (!done) {
3490 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003491 result->Add(argument);
Steve Blocka7e24c12009-10-30 11:49:00 +00003492 done = (peek() == Token::RPAREN);
3493 if (!done) Expect(Token::COMMA, CHECK_OK);
3494 }
3495 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003496 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003497}
3498
3499
3500FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
Steve Block1e0659c2011-05-24 12:43:12 +01003501 bool name_is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003502 int function_token_position,
3503 FunctionLiteralType type,
3504 bool* ok) {
3505 // Function ::
3506 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003507 bool is_named = !var_name.is_null();
3508
3509 // The name associated with this function. If it's a function expression,
3510 // this is the actual function name, otherwise this is the name of the
3511 // variable declared and initialized with the function (expression). In
3512 // that case, we don't have a function name (it's empty).
Steve Block44f0eee2011-05-26 01:26:41 +01003513 Handle<String> name =
3514 is_named ? var_name : isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003515 // The function name, if any.
Steve Block44f0eee2011-05-26 01:26:41 +01003516 Handle<String> function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003517 if (is_named && (type == EXPRESSION || type == NESTED)) {
3518 function_name = name;
3519 }
3520
3521 int num_parameters = 0;
3522 // Parse function body.
Ben Murdochf87a2032010-10-22 12:50:53 +01003523 { Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003524 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
Steve Block44f0eee2011-05-26 01:26:41 +01003525 LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003526 top_scope_->SetScopeName(name);
3527
3528 // FormalParameterList ::
3529 // '(' (Identifier)*[','] ')'
3530 Expect(Token::LPAREN, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003531 int start_pos = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01003532 Scanner::Location name_loc = Scanner::NoLocation();
3533 Scanner::Location dupe_loc = Scanner::NoLocation();
3534 Scanner::Location reserved_loc = Scanner::NoLocation();
3535
Steve Blocka7e24c12009-10-30 11:49:00 +00003536 bool done = (peek() == Token::RPAREN);
3537 while (!done) {
Steve Block1e0659c2011-05-24 12:43:12 +01003538 bool is_reserved = false;
3539 Handle<String> param_name =
3540 ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
3541
3542 // Store locations for possible future error reports.
3543 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3544 name_loc = scanner().location();
3545 }
3546 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
3547 dupe_loc = scanner().location();
3548 }
3549 if (!reserved_loc.IsValid() && is_reserved) {
3550 reserved_loc = scanner().location();
3551 }
3552
3553 Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR);
3554 top_scope_->AddParameter(parameter);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003555 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003556 if (num_parameters > kMaxNumFunctionParameters) {
3557 ReportMessageAt(scanner().location(), "too_many_parameters",
3558 Vector<const char*>::empty());
3559 *ok = false;
3560 return NULL;
3561 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003562 done = (peek() == Token::RPAREN);
3563 if (!done) Expect(Token::COMMA, CHECK_OK);
3564 }
3565 Expect(Token::RPAREN, CHECK_OK);
3566
3567 Expect(Token::LBRACE, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003568 ZoneList<Statement*>* body = new ZoneList<Statement*>(8);
Steve Blocka7e24c12009-10-30 11:49:00 +00003569
3570 // If we have a named function expression, we add a local variable
3571 // declaration to the body of the function with the name of the
3572 // function and let it refer to the function itself (closure).
3573 // NOTE: We create a proxy and resolve it here so that in the
3574 // future we can change the AST to only refer to VariableProxies
3575 // instead of Variables and Proxis as is the case now.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003576 if (!function_name.is_null() && function_name->length() > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003577 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3578 VariableProxy* fproxy =
3579 top_scope_->NewUnresolved(function_name, inside_with());
3580 fproxy->BindTo(fvar);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003581 body->Add(new ExpressionStatement(
3582 new Assignment(Token::INIT_CONST, fproxy,
3583 new ThisFunction(),
3584 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003585 }
3586
3587 // Determine if the function will be lazily compiled. The mode can
3588 // only be PARSE_LAZILY if the --lazy flag is true.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003589 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3590 top_scope_->outer_scope()->is_global_scope() &&
3591 top_scope_->HasTrivialOuterContext() &&
3592 !parenthesized_function_);
3593 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003594
Ben Murdochb0fe1622011-05-05 13:52:32 +01003595 int function_block_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003596 int materialized_literal_count;
3597 int expected_property_count;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003598 int end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003599 bool only_simple_this_property_assignments;
3600 Handle<FixedArray> this_property_assignments;
3601 if (is_lazily_compiled && pre_data() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003602 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003603 if (!entry.is_valid()) {
3604 ReportInvalidPreparseData(name, CHECK_OK);
3605 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003606 end_pos = entry.end_pos();
3607 if (end_pos <= function_block_pos) {
Leon Clarkeac952652010-07-15 11:15:24 +01003608 // End position greater than end of stream is safe, and hard to check.
3609 ReportInvalidPreparseData(name, CHECK_OK);
3610 }
Steve Block44f0eee2011-05-26 01:26:41 +01003611 isolate()->counters()->total_preparse_skipped()->Increment(
3612 end_pos - function_block_pos);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003613 // Seek to position just before terminal '}'.
3614 scanner().SeekForward(end_pos - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003615 materialized_literal_count = entry.literal_count();
3616 expected_property_count = entry.property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003617 only_simple_this_property_assignments = false;
Steve Block44f0eee2011-05-26 01:26:41 +01003618 this_property_assignments = isolate()->factory()->empty_fixed_array();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003619 Expect(Token::RBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003620 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003621 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3622
Steve Block44f0eee2011-05-26 01:26:41 +01003623 materialized_literal_count = lexical_scope.materialized_literal_count();
3624 expected_property_count = lexical_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003625 only_simple_this_property_assignments =
Steve Block44f0eee2011-05-26 01:26:41 +01003626 lexical_scope.only_simple_this_property_assignments();
3627 this_property_assignments = lexical_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003628
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003629 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003630 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003631 }
3632
Steve Block1e0659c2011-05-24 12:43:12 +01003633 // Validate strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01003634 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003635 if (IsEvalOrArguments(name)) {
3636 int position = function_token_position != RelocInfo::kNoPosition
3637 ? function_token_position
3638 : (start_pos > 0 ? start_pos - 1 : start_pos);
3639 Scanner::Location location = Scanner::Location(position, start_pos);
3640 ReportMessageAt(location,
3641 "strict_function_name", Vector<const char*>::empty());
3642 *ok = false;
3643 return NULL;
3644 }
3645 if (name_loc.IsValid()) {
3646 ReportMessageAt(name_loc, "strict_param_name",
3647 Vector<const char*>::empty());
3648 *ok = false;
3649 return NULL;
3650 }
3651 if (dupe_loc.IsValid()) {
3652 ReportMessageAt(dupe_loc, "strict_param_dupe",
3653 Vector<const char*>::empty());
3654 *ok = false;
3655 return NULL;
3656 }
3657 if (name_is_reserved) {
3658 int position = function_token_position != RelocInfo::kNoPosition
3659 ? function_token_position
3660 : (start_pos > 0 ? start_pos - 1 : start_pos);
3661 Scanner::Location location = Scanner::Location(position, start_pos);
3662 ReportMessageAt(location, "strict_reserved_word",
3663 Vector<const char*>::empty());
3664 *ok = false;
3665 return NULL;
3666 }
3667 if (reserved_loc.IsValid()) {
3668 ReportMessageAt(reserved_loc, "strict_reserved_word",
3669 Vector<const char*>::empty());
3670 *ok = false;
3671 return NULL;
3672 }
3673 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3674 }
3675
Steve Blocka7e24c12009-10-30 11:49:00 +00003676 FunctionLiteral* function_literal =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003677 new FunctionLiteral(name,
Steve Blocka7e24c12009-10-30 11:49:00 +00003678 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003679 body,
Steve Blocka7e24c12009-10-30 11:49:00 +00003680 materialized_literal_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 expected_property_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003682 only_simple_this_property_assignments,
3683 this_property_assignments,
3684 num_parameters,
3685 start_pos,
3686 end_pos,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003687 function_name->length() > 0,
Steve Block44f0eee2011-05-26 01:26:41 +01003688 lexical_scope.ContainsLoops());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003689 function_literal->set_function_token_position(function_token_position);
Steve Block6ded16b2010-05-10 14:33:55 +01003690
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003691 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
Steve Blocka7e24c12009-10-30 11:49:00 +00003692 return function_literal;
3693 }
3694}
3695
3696
3697Expression* Parser::ParseV8Intrinsic(bool* ok) {
3698 // CallRuntime ::
3699 // '%' Identifier Arguments
3700
3701 Expect(Token::MOD, CHECK_OK);
3702 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003703 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003704
3705 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003706 // The extension structures are only accessible while parsing the
3707 // very first time not when reparsing because of lazy compilation.
3708 top_scope_->ForceEagerCompilation();
3709 }
3710
Steve Block44f0eee2011-05-26 01:26:41 +01003711 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003712
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003713 // Check for built-in IS_VAR macro.
3714 if (function != NULL &&
3715 function->intrinsic_type == Runtime::RUNTIME &&
3716 function->function_id == Runtime::kIS_VAR) {
3717 // %IS_VAR(x) evaluates to x if x is a variable,
3718 // leads to a parse error otherwise. Could be implemented as an
3719 // inline function %_IS_VAR(x) to eliminate this special case.
3720 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3721 return args->at(0);
3722 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003723 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003724 *ok = false;
3725 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003726 }
3727 }
3728
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003729 // Check that the expected number of arguments are being passed.
3730 if (function != NULL &&
3731 function->nargs != -1 &&
3732 function->nargs != args->length()) {
3733 ReportMessage("illegal_access", Vector<const char*>::empty());
3734 *ok = false;
3735 return NULL;
3736 }
3737
3738 // We have a valid intrinsics call or a call to a builtin.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003739 return new CallRuntime(name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003740}
3741
3742
Steve Block1e0659c2011-05-24 12:43:12 +01003743bool Parser::peek_any_identifier() {
3744 Token::Value next = peek();
3745 return next == Token::IDENTIFIER ||
3746 next == Token::FUTURE_RESERVED_WORD;
3747}
3748
3749
Steve Blocka7e24c12009-10-30 11:49:00 +00003750void Parser::Consume(Token::Value token) {
3751 Token::Value next = Next();
3752 USE(next);
3753 USE(token);
3754 ASSERT(next == token);
3755}
3756
3757
3758void Parser::Expect(Token::Value token, bool* ok) {
3759 Token::Value next = Next();
3760 if (next == token) return;
3761 ReportUnexpectedToken(next);
3762 *ok = false;
3763}
3764
3765
Leon Clarke4515c472010-02-03 11:58:03 +00003766bool Parser::Check(Token::Value token) {
3767 Token::Value next = peek();
3768 if (next == token) {
3769 Consume(next);
3770 return true;
3771 }
3772 return false;
3773}
3774
3775
Steve Blocka7e24c12009-10-30 11:49:00 +00003776void Parser::ExpectSemicolon(bool* ok) {
3777 // Check for automatic semicolon insertion according to
3778 // the rules given in ECMA-262, section 7.9, page 21.
3779 Token::Value tok = peek();
3780 if (tok == Token::SEMICOLON) {
3781 Next();
3782 return;
3783 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003784 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003785 tok == Token::RBRACE ||
3786 tok == Token::EOS) {
3787 return;
3788 }
3789 Expect(Token::SEMICOLON, ok);
3790}
3791
3792
3793Literal* Parser::GetLiteralUndefined() {
Steve Block44f0eee2011-05-26 01:26:41 +01003794 return new Literal(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003795}
3796
3797
3798Literal* Parser::GetLiteralTheHole() {
Steve Block44f0eee2011-05-26 01:26:41 +01003799 return new Literal(isolate()->factory()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003800}
3801
3802
3803Literal* Parser::GetLiteralNumber(double value) {
3804 return NewNumberLiteral(value);
3805}
3806
3807
3808Handle<String> Parser::ParseIdentifier(bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003809 bool is_reserved;
3810 return ParseIdentifierOrReservedWord(&is_reserved, ok);
3811}
3812
3813
3814Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved,
3815 bool* ok) {
3816 *is_reserved = false;
Steve Block44f0eee2011-05-26 01:26:41 +01003817 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003818 Expect(Token::IDENTIFIER, ok);
3819 } else {
3820 if (!Check(Token::IDENTIFIER)) {
3821 Expect(Token::FUTURE_RESERVED_WORD, ok);
3822 *is_reserved = true;
3823 }
3824 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003825 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003826 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003827}
3828
Ben Murdochbb769b22010-08-11 14:56:33 +01003829
3830Handle<String> Parser::ParseIdentifierName(bool* ok) {
3831 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01003832 if (next != Token::IDENTIFIER &&
3833 next != Token::FUTURE_RESERVED_WORD &&
3834 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01003835 ReportUnexpectedToken(next);
3836 *ok = false;
3837 return Handle<String>();
3838 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003839 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01003840}
3841
3842
Steve Block1e0659c2011-05-24 12:43:12 +01003843// Checks LHS expression for assignment and prefix/postfix increment/decrement
3844// in strict mode.
3845void Parser::CheckStrictModeLValue(Expression* expression,
3846 const char* error,
3847 bool* ok) {
Steve Block44f0eee2011-05-26 01:26:41 +01003848 ASSERT(top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003849 VariableProxy* lhs = expression != NULL
3850 ? expression->AsVariableProxy()
3851 : NULL;
3852
3853 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
3854 ReportMessage(error, Vector<const char*>::empty());
3855 *ok = false;
3856 }
3857}
3858
3859
3860// Checks whether octal literal last seen is between beg_pos and end_pos.
3861// If so, reports an error.
3862void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
3863 int octal = scanner().octal_position();
3864 if (beg_pos <= octal && octal <= end_pos) {
3865 ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal",
3866 Vector<const char*>::empty());
3867 scanner().clear_octal_position();
3868 *ok = false;
3869 }
3870}
3871
3872
Steve Blocka7e24c12009-10-30 11:49:00 +00003873// This function reads an identifier and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01003874// is 'get' or 'set'.
Steve Blocka7e24c12009-10-30 11:49:00 +00003875Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3876 bool* is_set,
3877 bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003878 Handle<String> result = ParseIdentifier(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003879 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01003880 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
3881 const char* token = scanner().literal_ascii_string().start();
3882 *is_get = strncmp(token, "get", 3) == 0;
3883 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003884 }
Steve Block1e0659c2011-05-24 12:43:12 +01003885 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003886}
3887
3888
3889// ----------------------------------------------------------------------------
3890// Parser support
3891
3892
3893bool Parser::TargetStackContainsLabel(Handle<String> label) {
3894 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3895 BreakableStatement* stat = t->node()->AsBreakableStatement();
3896 if (stat != NULL && ContainsLabel(stat->labels(), label))
3897 return true;
3898 }
3899 return false;
3900}
3901
3902
3903BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3904 bool anonymous = label.is_null();
3905 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3906 BreakableStatement* stat = t->node()->AsBreakableStatement();
3907 if (stat == NULL) continue;
3908 if ((anonymous && stat->is_target_for_anonymous()) ||
3909 (!anonymous && ContainsLabel(stat->labels(), label))) {
3910 RegisterTargetUse(stat->break_target(), t->previous());
3911 return stat;
3912 }
3913 }
3914 return NULL;
3915}
3916
3917
3918IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3919 bool* ok) {
3920 bool anonymous = label.is_null();
3921 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3922 IterationStatement* stat = t->node()->AsIterationStatement();
3923 if (stat == NULL) continue;
3924
3925 ASSERT(stat->is_target_for_anonymous());
3926 if (anonymous || ContainsLabel(stat->labels(), label)) {
3927 RegisterTargetUse(stat->continue_target(), t->previous());
3928 return stat;
3929 }
3930 }
3931 return NULL;
3932}
3933
3934
3935void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) {
3936 // Register that a break target found at the given stop in the
3937 // target stack has been used from the top of the target stack. Add
3938 // the break target to any TargetCollectors passed on the stack.
3939 for (Target* t = target_stack_; t != stop; t = t->previous()) {
3940 TargetCollector* collector = t->node()->AsTargetCollector();
3941 if (collector != NULL) collector->AddTarget(target);
3942 }
3943}
3944
3945
3946Literal* Parser::NewNumberLiteral(double number) {
Steve Block44f0eee2011-05-26 01:26:41 +01003947 return new Literal(isolate()->factory()->NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00003948}
3949
3950
3951Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01003952 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00003953 type, HandleVector<Object>(NULL, 0));
3954}
3955
3956
3957Expression* Parser::NewThrowSyntaxError(Handle<String> type,
3958 Handle<Object> first) {
3959 int argc = first.is_null() ? 0 : 1;
3960 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01003961 return NewThrowError(
3962 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00003963}
3964
3965
3966Expression* Parser::NewThrowTypeError(Handle<String> type,
3967 Handle<Object> first,
3968 Handle<Object> second) {
3969 ASSERT(!first.is_null() && !second.is_null());
3970 Handle<Object> elements[] = { first, second };
3971 Vector< Handle<Object> > arguments =
3972 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01003973 return NewThrowError(
3974 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00003975}
3976
3977
3978Expression* Parser::NewThrowError(Handle<String> constructor,
3979 Handle<String> type,
3980 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003981 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01003982 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
3983 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003984 for (int i = 0; i < argc; i++) {
3985 Handle<Object> element = arguments[i];
3986 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003987 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00003988 }
3989 }
Steve Block44f0eee2011-05-26 01:26:41 +01003990 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
3991 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01003992
Steve Blocka7e24c12009-10-30 11:49:00 +00003993 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
3994 args->Add(new Literal(type));
3995 args->Add(new Literal(array));
3996 return new Throw(new CallRuntime(constructor, NULL, args),
3997 scanner().location().beg_pos);
3998}
3999
Leon Clarke4515c472010-02-03 11:58:03 +00004000// ----------------------------------------------------------------------------
4001// JSON
4002
Ben Murdochb0fe1622011-05-05 13:52:32 +01004003Handle<Object> JsonParser::ParseJson(Handle<String> script,
4004 UC16CharacterStream* source) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004005 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004006 stack_overflow_ = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004007 Handle<Object> result = ParseJsonValue();
4008 if (result.is_null() || scanner_.Next() != Token::EOS) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004009 if (stack_overflow_) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004010 // Scanner failed.
Steve Block44f0eee2011-05-26 01:26:41 +01004011 isolate()->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004012 } else {
4013 // Parse failed. Scanner's current token is the unexpected token.
4014 Token::Value token = scanner_.current_token();
4015
4016 const char* message;
4017 const char* name_opt = NULL;
4018
4019 switch (token) {
4020 case Token::EOS:
4021 message = "unexpected_eos";
4022 break;
4023 case Token::NUMBER:
4024 message = "unexpected_token_number";
4025 break;
4026 case Token::STRING:
4027 message = "unexpected_token_string";
4028 break;
4029 case Token::IDENTIFIER:
Steve Block1e0659c2011-05-24 12:43:12 +01004030 case Token::FUTURE_RESERVED_WORD:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004031 message = "unexpected_token_identifier";
4032 break;
4033 default:
4034 message = "unexpected_token";
4035 name_opt = Token::String(token);
4036 ASSERT(name_opt != NULL);
4037 break;
4038 }
4039
4040 Scanner::Location source_location = scanner_.location();
Steve Block44f0eee2011-05-26 01:26:41 +01004041 Factory* factory = isolate()->factory();
4042 MessageLocation location(factory->NewScript(script),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004043 source_location.beg_pos,
4044 source_location.end_pos);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004045 Handle<JSArray> array;
4046 if (name_opt == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +01004047 array = factory->NewJSArray(0);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004048 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004049 Handle<String> name = factory->NewStringFromUtf8(CStrVector(name_opt));
4050 Handle<FixedArray> element = factory->NewFixedArray(1);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004051 element->set(0, *name);
Steve Block44f0eee2011-05-26 01:26:41 +01004052 array = factory->NewJSArrayWithElements(element);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004053 }
Steve Block44f0eee2011-05-26 01:26:41 +01004054 Handle<Object> result = factory->NewSyntaxError(message, array);
4055 isolate()->Throw(*result, &location);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004056 return Handle<Object>::null();
4057 }
4058 }
Leon Clarke4515c472010-02-03 11:58:03 +00004059 return result;
4060}
4061
4062
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004063Handle<String> JsonParser::GetString() {
4064 int literal_length = scanner_.literal_length();
4065 if (literal_length == 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01004066 return isolate()->factory()->empty_string();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004067 }
Steve Block9fac8402011-05-12 15:51:54 +01004068 if (scanner_.is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004069 return isolate()->factory()->NewStringFromAscii(
4070 scanner_.literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +01004071 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004072 return isolate()->factory()->NewStringFromTwoByte(
4073 scanner_.literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +01004074 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004075}
4076
4077
Leon Clarke4515c472010-02-03 11:58:03 +00004078// Parse any JSON value.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004079Handle<Object> JsonParser::ParseJsonValue() {
4080 Token::Value token = scanner_.Next();
Leon Clarke4515c472010-02-03 11:58:03 +00004081 switch (token) {
Steve Block1e0659c2011-05-24 12:43:12 +01004082 case Token::STRING:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004083 return GetString();
Steve Block1e0659c2011-05-24 12:43:12 +01004084 case Token::NUMBER:
Steve Block44f0eee2011-05-26 01:26:41 +01004085 return isolate()->factory()->NewNumber(scanner_.number());
Leon Clarke4515c472010-02-03 11:58:03 +00004086 case Token::FALSE_LITERAL:
Steve Block44f0eee2011-05-26 01:26:41 +01004087 return isolate()->factory()->false_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004088 case Token::TRUE_LITERAL:
Steve Block44f0eee2011-05-26 01:26:41 +01004089 return isolate()->factory()->true_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004090 case Token::NULL_LITERAL:
Steve Block44f0eee2011-05-26 01:26:41 +01004091 return isolate()->factory()->null_value();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004092 case Token::LBRACE:
4093 return ParseJsonObject();
4094 case Token::LBRACK:
4095 return ParseJsonArray();
Leon Clarke4515c472010-02-03 11:58:03 +00004096 default:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004097 return ReportUnexpectedToken();
Leon Clarke4515c472010-02-03 11:58:03 +00004098 }
4099}
4100
4101
4102// Parse a JSON object. Scanner must be right after '{' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004103Handle<Object> JsonParser::ParseJsonObject() {
4104 Handle<JSFunction> object_constructor(
Steve Block44f0eee2011-05-26 01:26:41 +01004105 isolate()->global_context()->object_function());
4106 Handle<JSObject> json_object =
4107 isolate()->factory()->NewJSObject(object_constructor);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004108 if (scanner_.peek() == Token::RBRACE) {
4109 scanner_.Next();
4110 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004111 if (StackLimitCheck(isolate()).HasOverflowed()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004112 stack_overflow_ = true;
4113 return Handle<Object>::null();
4114 }
Leon Clarke4515c472010-02-03 11:58:03 +00004115 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004116 if (scanner_.Next() != Token::STRING) {
4117 return ReportUnexpectedToken();
4118 }
4119 Handle<String> key = GetString();
4120 if (scanner_.Next() != Token::COLON) {
4121 return ReportUnexpectedToken();
4122 }
4123 Handle<Object> value = ParseJsonValue();
4124 if (value.is_null()) return Handle<Object>::null();
Leon Clarke4515c472010-02-03 11:58:03 +00004125 uint32_t index;
4126 if (key->AsArrayIndex(&index)) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004127 SetOwnElement(json_object, index, value, kNonStrictMode);
Steve Block44f0eee2011-05-26 01:26:41 +01004128 } else if (key->Equals(isolate()->heap()->Proto_symbol())) {
Steve Block1e0659c2011-05-24 12:43:12 +01004129 // We can't remove the __proto__ accessor since it's hardcoded
4130 // in several places. Instead go along and add the value as
4131 // the prototype of the created object if possible.
4132 SetPrototype(json_object, value);
Leon Clarke4515c472010-02-03 11:58:03 +00004133 } else {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004134 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
Leon Clarke4515c472010-02-03 11:58:03 +00004135 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004136 } while (scanner_.Next() == Token::COMMA);
4137 if (scanner_.current_token() != Token::RBRACE) {
4138 return ReportUnexpectedToken();
4139 }
Leon Clarke4515c472010-02-03 11:58:03 +00004140 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004141 return json_object;
Leon Clarke4515c472010-02-03 11:58:03 +00004142}
4143
4144
4145// Parse a JSON array. Scanner must be right after '[' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004146Handle<Object> JsonParser::ParseJsonArray() {
4147 ZoneScope zone_scope(DELETE_ON_EXIT);
4148 ZoneList<Handle<Object> > elements(4);
Leon Clarke4515c472010-02-03 11:58:03 +00004149
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004150 Token::Value token = scanner_.peek();
4151 if (token == Token::RBRACK) {
4152 scanner_.Next();
4153 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01004154 if (StackLimitCheck(isolate()).HasOverflowed()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004155 stack_overflow_ = true;
4156 return Handle<Object>::null();
4157 }
Leon Clarke4515c472010-02-03 11:58:03 +00004158 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004159 Handle<Object> element = ParseJsonValue();
4160 if (element.is_null()) return Handle<Object>::null();
4161 elements.Add(element);
4162 token = scanner_.Next();
4163 } while (token == Token::COMMA);
4164 if (token != Token::RBRACK) {
4165 return ReportUnexpectedToken();
4166 }
Leon Clarke4515c472010-02-03 11:58:03 +00004167 }
Leon Clarke4515c472010-02-03 11:58:03 +00004168
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004169 // Allocate a fixed array with all the elements.
4170 Handle<FixedArray> fast_elements =
Steve Block44f0eee2011-05-26 01:26:41 +01004171 isolate()->factory()->NewFixedArray(elements.length());
Leon Clarke4515c472010-02-03 11:58:03 +00004172
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004173 for (int i = 0, n = elements.length(); i < n; i++) {
4174 fast_elements->set(i, *elements[i]);
4175 }
Leon Clarke4515c472010-02-03 11:58:03 +00004176
Steve Block44f0eee2011-05-26 01:26:41 +01004177 return isolate()->factory()->NewJSArrayWithElements(fast_elements);
Leon Clarke4515c472010-02-03 11:58:03 +00004178}
4179
Steve Blocka7e24c12009-10-30 11:49:00 +00004180// ----------------------------------------------------------------------------
4181// Regular expressions
4182
4183
4184RegExpParser::RegExpParser(FlatStringReader* in,
4185 Handle<String>* error,
4186 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004187 : isolate_(Isolate::Current()),
4188 error_(error),
4189 captures_(NULL),
4190 in_(in),
4191 current_(kEndMarker),
4192 next_pos_(0),
4193 capture_count_(0),
4194 has_more_(true),
4195 multiline_(multiline),
4196 simple_(false),
4197 contains_anchor_(false),
4198 is_scanned_for_captures_(false),
4199 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004200 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004201}
4202
4203
4204uc32 RegExpParser::Next() {
4205 if (has_next()) {
4206 return in()->Get(next_pos_);
4207 } else {
4208 return kEndMarker;
4209 }
4210}
4211
4212
4213void RegExpParser::Advance() {
4214 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004215 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004216 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004217 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4218 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004219 ReportError(CStrVector("Regular expression too large"));
4220 } else {
4221 current_ = in()->Get(next_pos_);
4222 next_pos_++;
4223 }
4224 } else {
4225 current_ = kEndMarker;
4226 has_more_ = false;
4227 }
4228}
4229
4230
4231void RegExpParser::Reset(int pos) {
4232 next_pos_ = pos;
4233 Advance();
4234}
4235
4236
4237void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004238 next_pos_ += dist - 1;
4239 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004240}
4241
4242
4243bool RegExpParser::simple() {
4244 return simple_;
4245}
4246
4247RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4248 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004249 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004250 // Zip to the end to make sure the no more input is read.
4251 current_ = kEndMarker;
4252 next_pos_ = in()->length();
4253 return NULL;
4254}
4255
4256
4257// Pattern ::
4258// Disjunction
4259RegExpTree* RegExpParser::ParsePattern() {
4260 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4261 ASSERT(!has_more());
4262 // If the result of parsing is a literal string atom, and it has the
4263 // same length as the input, then the atom is identical to the input.
4264 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4265 simple_ = true;
4266 }
4267 return result;
4268}
4269
4270
4271// Disjunction ::
4272// Alternative
4273// Alternative | Disjunction
4274// Alternative ::
4275// [empty]
4276// Term Alternative
4277// Term ::
4278// Assertion
4279// Atom
4280// Atom Quantifier
4281RegExpTree* RegExpParser::ParseDisjunction() {
4282 // Used to store current state while parsing subexpressions.
4283 RegExpParserState initial_state(NULL, INITIAL, 0);
4284 RegExpParserState* stored_state = &initial_state;
4285 // Cache the builder in a local variable for quick access.
4286 RegExpBuilder* builder = initial_state.builder();
4287 while (true) {
4288 switch (current()) {
4289 case kEndMarker:
4290 if (stored_state->IsSubexpression()) {
4291 // Inside a parenthesized group when hitting end of input.
4292 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4293 }
4294 ASSERT_EQ(INITIAL, stored_state->group_type());
4295 // Parsing completed successfully.
4296 return builder->ToRegExp();
4297 case ')': {
4298 if (!stored_state->IsSubexpression()) {
4299 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4300 }
4301 ASSERT_NE(INITIAL, stored_state->group_type());
4302
4303 Advance();
4304 // End disjunction parsing and convert builder content to new single
4305 // regexp atom.
4306 RegExpTree* body = builder->ToRegExp();
4307
4308 int end_capture_index = captures_started();
4309
4310 int capture_index = stored_state->capture_index();
4311 SubexpressionType type = stored_state->group_type();
4312
4313 // Restore previous state.
4314 stored_state = stored_state->previous_state();
4315 builder = stored_state->builder();
4316
4317 // Build result of subexpression.
4318 if (type == CAPTURE) {
4319 RegExpCapture* capture = new RegExpCapture(body, capture_index);
4320 captures_->at(capture_index - 1) = capture;
4321 body = capture;
4322 } else if (type != GROUPING) {
4323 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4324 bool is_positive = (type == POSITIVE_LOOKAHEAD);
4325 body = new RegExpLookahead(body,
4326 is_positive,
4327 end_capture_index - capture_index,
4328 capture_index);
4329 }
4330 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004331 // For compatability with JSC and ES3, we allow quantifiers after
4332 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004333 break;
4334 }
4335 case '|': {
4336 Advance();
4337 builder->NewAlternative();
4338 continue;
4339 }
4340 case '*':
4341 case '+':
4342 case '?':
4343 return ReportError(CStrVector("Nothing to repeat"));
4344 case '^': {
4345 Advance();
4346 if (multiline_) {
4347 builder->AddAssertion(
4348 new RegExpAssertion(RegExpAssertion::START_OF_LINE));
4349 } else {
4350 builder->AddAssertion(
4351 new RegExpAssertion(RegExpAssertion::START_OF_INPUT));
4352 set_contains_anchor();
4353 }
4354 continue;
4355 }
4356 case '$': {
4357 Advance();
4358 RegExpAssertion::Type type =
4359 multiline_ ? RegExpAssertion::END_OF_LINE :
4360 RegExpAssertion::END_OF_INPUT;
4361 builder->AddAssertion(new RegExpAssertion(type));
4362 continue;
4363 }
4364 case '.': {
4365 Advance();
4366 // everything except \x0a, \x0d, \u2028 and \u2029
4367 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4368 CharacterRange::AddClassEscape('.', ranges);
4369 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
4370 builder->AddAtom(atom);
4371 break;
4372 }
4373 case '(': {
4374 SubexpressionType type = CAPTURE;
4375 Advance();
4376 if (current() == '?') {
4377 switch (Next()) {
4378 case ':':
4379 type = GROUPING;
4380 break;
4381 case '=':
4382 type = POSITIVE_LOOKAHEAD;
4383 break;
4384 case '!':
4385 type = NEGATIVE_LOOKAHEAD;
4386 break;
4387 default:
4388 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4389 break;
4390 }
4391 Advance(2);
4392 } else {
4393 if (captures_ == NULL) {
4394 captures_ = new ZoneList<RegExpCapture*>(2);
4395 }
4396 if (captures_started() >= kMaxCaptures) {
4397 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4398 }
4399 captures_->Add(NULL);
4400 }
4401 // Store current state and begin new disjunction parsing.
4402 stored_state = new RegExpParserState(stored_state,
4403 type,
4404 captures_started());
4405 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004406 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004407 }
4408 case '[': {
4409 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4410 builder->AddAtom(atom);
4411 break;
4412 }
4413 // Atom ::
4414 // \ AtomEscape
4415 case '\\':
4416 switch (Next()) {
4417 case kEndMarker:
4418 return ReportError(CStrVector("\\ at end of pattern"));
4419 case 'b':
4420 Advance(2);
4421 builder->AddAssertion(
4422 new RegExpAssertion(RegExpAssertion::BOUNDARY));
4423 continue;
4424 case 'B':
4425 Advance(2);
4426 builder->AddAssertion(
4427 new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
4428 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004429 // AtomEscape ::
4430 // CharacterClassEscape
4431 //
4432 // CharacterClassEscape :: one of
4433 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004434 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4435 uc32 c = Next();
4436 Advance(2);
4437 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4438 CharacterRange::AddClassEscape(c, ranges);
4439 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
4440 builder->AddAtom(atom);
4441 break;
4442 }
4443 case '1': case '2': case '3': case '4': case '5': case '6':
4444 case '7': case '8': case '9': {
4445 int index = 0;
4446 if (ParseBackReferenceIndex(&index)) {
4447 RegExpCapture* capture = NULL;
4448 if (captures_ != NULL && index <= captures_->length()) {
4449 capture = captures_->at(index - 1);
4450 }
4451 if (capture == NULL) {
4452 builder->AddEmpty();
4453 break;
4454 }
4455 RegExpTree* atom = new RegExpBackReference(capture);
4456 builder->AddAtom(atom);
4457 break;
4458 }
4459 uc32 first_digit = Next();
4460 if (first_digit == '8' || first_digit == '9') {
4461 // Treat as identity escape
4462 builder->AddCharacter(first_digit);
4463 Advance(2);
4464 break;
4465 }
4466 }
4467 // FALLTHROUGH
4468 case '0': {
4469 Advance();
4470 uc32 octal = ParseOctalLiteral();
4471 builder->AddCharacter(octal);
4472 break;
4473 }
4474 // ControlEscape :: one of
4475 // f n r t v
4476 case 'f':
4477 Advance(2);
4478 builder->AddCharacter('\f');
4479 break;
4480 case 'n':
4481 Advance(2);
4482 builder->AddCharacter('\n');
4483 break;
4484 case 'r':
4485 Advance(2);
4486 builder->AddCharacter('\r');
4487 break;
4488 case 't':
4489 Advance(2);
4490 builder->AddCharacter('\t');
4491 break;
4492 case 'v':
4493 Advance(2);
4494 builder->AddCharacter('\v');
4495 break;
4496 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004497 Advance();
4498 uc32 controlLetter = Next();
4499 // Special case if it is an ASCII letter.
4500 // Convert lower case letters to uppercase.
4501 uc32 letter = controlLetter & ~('a' ^ 'A');
4502 if (letter < 'A' || 'Z' < letter) {
4503 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4504 // This is outside the specification. We match JSC in
4505 // reading the backslash as a literal character instead
4506 // of as starting an escape.
4507 builder->AddCharacter('\\');
4508 } else {
4509 Advance(2);
4510 builder->AddCharacter(controlLetter & 0x1f);
4511 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004512 break;
4513 }
4514 case 'x': {
4515 Advance(2);
4516 uc32 value;
4517 if (ParseHexEscape(2, &value)) {
4518 builder->AddCharacter(value);
4519 } else {
4520 builder->AddCharacter('x');
4521 }
4522 break;
4523 }
4524 case 'u': {
4525 Advance(2);
4526 uc32 value;
4527 if (ParseHexEscape(4, &value)) {
4528 builder->AddCharacter(value);
4529 } else {
4530 builder->AddCharacter('u');
4531 }
4532 break;
4533 }
4534 default:
4535 // Identity escape.
4536 builder->AddCharacter(Next());
4537 Advance(2);
4538 break;
4539 }
4540 break;
4541 case '{': {
4542 int dummy;
4543 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4544 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4545 }
4546 // fallthrough
4547 }
4548 default:
4549 builder->AddCharacter(current());
4550 Advance();
4551 break;
4552 } // end switch(current())
4553
4554 int min;
4555 int max;
4556 switch (current()) {
4557 // QuantifierPrefix ::
4558 // *
4559 // +
4560 // ?
4561 // {
4562 case '*':
4563 min = 0;
4564 max = RegExpTree::kInfinity;
4565 Advance();
4566 break;
4567 case '+':
4568 min = 1;
4569 max = RegExpTree::kInfinity;
4570 Advance();
4571 break;
4572 case '?':
4573 min = 0;
4574 max = 1;
4575 Advance();
4576 break;
4577 case '{':
4578 if (ParseIntervalQuantifier(&min, &max)) {
4579 if (max < min) {
4580 ReportError(CStrVector("numbers out of order in {} quantifier.")
4581 CHECK_FAILED);
4582 }
4583 break;
4584 } else {
4585 continue;
4586 }
4587 default:
4588 continue;
4589 }
Leon Clarkee46be812010-01-19 14:06:41 +00004590 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004591 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004592 type = RegExpQuantifier::NON_GREEDY;
4593 Advance();
4594 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4595 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4596 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004597 Advance();
4598 }
Leon Clarkee46be812010-01-19 14:06:41 +00004599 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004600 }
4601}
4602
Steve Blocka7e24c12009-10-30 11:49:00 +00004603
4604#ifdef DEBUG
4605// Currently only used in an ASSERT.
4606static bool IsSpecialClassEscape(uc32 c) {
4607 switch (c) {
4608 case 'd': case 'D':
4609 case 's': case 'S':
4610 case 'w': case 'W':
4611 return true;
4612 default:
4613 return false;
4614 }
4615}
4616#endif
4617
4618
4619// In order to know whether an escape is a backreference or not we have to scan
4620// the entire regexp and find the number of capturing parentheses. However we
4621// don't want to scan the regexp twice unless it is necessary. This mini-parser
4622// is called when needed. It can see the difference between capturing and
4623// noncapturing parentheses and can skip character classes and backslash-escaped
4624// characters.
4625void RegExpParser::ScanForCaptures() {
4626 // Start with captures started previous to current position
4627 int capture_count = captures_started();
4628 // Add count of captures after this position.
4629 int n;
4630 while ((n = current()) != kEndMarker) {
4631 Advance();
4632 switch (n) {
4633 case '\\':
4634 Advance();
4635 break;
4636 case '[': {
4637 int c;
4638 while ((c = current()) != kEndMarker) {
4639 Advance();
4640 if (c == '\\') {
4641 Advance();
4642 } else {
4643 if (c == ']') break;
4644 }
4645 }
4646 break;
4647 }
4648 case '(':
4649 if (current() != '?') capture_count++;
4650 break;
4651 }
4652 }
4653 capture_count_ = capture_count;
4654 is_scanned_for_captures_ = true;
4655}
4656
4657
4658bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4659 ASSERT_EQ('\\', current());
4660 ASSERT('1' <= Next() && Next() <= '9');
4661 // Try to parse a decimal literal that is no greater than the total number
4662 // of left capturing parentheses in the input.
4663 int start = position();
4664 int value = Next() - '0';
4665 Advance(2);
4666 while (true) {
4667 uc32 c = current();
4668 if (IsDecimalDigit(c)) {
4669 value = 10 * value + (c - '0');
4670 if (value > kMaxCaptures) {
4671 Reset(start);
4672 return false;
4673 }
4674 Advance();
4675 } else {
4676 break;
4677 }
4678 }
4679 if (value > captures_started()) {
4680 if (!is_scanned_for_captures_) {
4681 int saved_position = position();
4682 ScanForCaptures();
4683 Reset(saved_position);
4684 }
4685 if (value > capture_count_) {
4686 Reset(start);
4687 return false;
4688 }
4689 }
4690 *index_out = value;
4691 return true;
4692}
4693
4694
4695// QuantifierPrefix ::
4696// { DecimalDigits }
4697// { DecimalDigits , }
4698// { DecimalDigits , DecimalDigits }
4699//
4700// Returns true if parsing succeeds, and set the min_out and max_out
4701// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4702bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4703 ASSERT_EQ(current(), '{');
4704 int start = position();
4705 Advance();
4706 int min = 0;
4707 if (!IsDecimalDigit(current())) {
4708 Reset(start);
4709 return false;
4710 }
4711 while (IsDecimalDigit(current())) {
4712 int next = current() - '0';
4713 if (min > (RegExpTree::kInfinity - next) / 10) {
4714 // Overflow. Skip past remaining decimal digits and return -1.
4715 do {
4716 Advance();
4717 } while (IsDecimalDigit(current()));
4718 min = RegExpTree::kInfinity;
4719 break;
4720 }
4721 min = 10 * min + next;
4722 Advance();
4723 }
4724 int max = 0;
4725 if (current() == '}') {
4726 max = min;
4727 Advance();
4728 } else if (current() == ',') {
4729 Advance();
4730 if (current() == '}') {
4731 max = RegExpTree::kInfinity;
4732 Advance();
4733 } else {
4734 while (IsDecimalDigit(current())) {
4735 int next = current() - '0';
4736 if (max > (RegExpTree::kInfinity - next) / 10) {
4737 do {
4738 Advance();
4739 } while (IsDecimalDigit(current()));
4740 max = RegExpTree::kInfinity;
4741 break;
4742 }
4743 max = 10 * max + next;
4744 Advance();
4745 }
4746 if (current() != '}') {
4747 Reset(start);
4748 return false;
4749 }
4750 Advance();
4751 }
4752 } else {
4753 Reset(start);
4754 return false;
4755 }
4756 *min_out = min;
4757 *max_out = max;
4758 return true;
4759}
4760
4761
Steve Blocka7e24c12009-10-30 11:49:00 +00004762uc32 RegExpParser::ParseOctalLiteral() {
4763 ASSERT('0' <= current() && current() <= '7');
4764 // For compatibility with some other browsers (not all), we parse
4765 // up to three octal digits with a value below 256.
4766 uc32 value = current() - '0';
4767 Advance();
4768 if ('0' <= current() && current() <= '7') {
4769 value = value * 8 + current() - '0';
4770 Advance();
4771 if (value < 32 && '0' <= current() && current() <= '7') {
4772 value = value * 8 + current() - '0';
4773 Advance();
4774 }
4775 }
4776 return value;
4777}
4778
4779
4780bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4781 int start = position();
4782 uc32 val = 0;
4783 bool done = false;
4784 for (int i = 0; !done; i++) {
4785 uc32 c = current();
4786 int d = HexValue(c);
4787 if (d < 0) {
4788 Reset(start);
4789 return false;
4790 }
4791 val = val * 16 + d;
4792 Advance();
4793 if (i == length - 1) {
4794 done = true;
4795 }
4796 }
4797 *value = val;
4798 return true;
4799}
4800
4801
4802uc32 RegExpParser::ParseClassCharacterEscape() {
4803 ASSERT(current() == '\\');
4804 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4805 Advance();
4806 switch (current()) {
4807 case 'b':
4808 Advance();
4809 return '\b';
4810 // ControlEscape :: one of
4811 // f n r t v
4812 case 'f':
4813 Advance();
4814 return '\f';
4815 case 'n':
4816 Advance();
4817 return '\n';
4818 case 'r':
4819 Advance();
4820 return '\r';
4821 case 't':
4822 Advance();
4823 return '\t';
4824 case 'v':
4825 Advance();
4826 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004827 case 'c': {
4828 uc32 controlLetter = Next();
4829 uc32 letter = controlLetter & ~('A' ^ 'a');
4830 // For compatibility with JSC, inside a character class
4831 // we also accept digits and underscore as control characters.
4832 if ((controlLetter >= '0' && controlLetter <= '9') ||
4833 controlLetter == '_' ||
4834 (letter >= 'A' && letter <= 'Z')) {
4835 Advance(2);
4836 // Control letters mapped to ASCII control characters in the range
4837 // 0x00-0x1f.
4838 return controlLetter & 0x1f;
4839 }
4840 // We match JSC in reading the backslash as a literal
4841 // character instead of as starting an escape.
4842 return '\\';
4843 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004844 case '0': case '1': case '2': case '3': case '4': case '5':
4845 case '6': case '7':
4846 // For compatibility, we interpret a decimal escape that isn't
4847 // a back reference (and therefore either \0 or not valid according
4848 // to the specification) as a 1..3 digit octal character code.
4849 return ParseOctalLiteral();
4850 case 'x': {
4851 Advance();
4852 uc32 value;
4853 if (ParseHexEscape(2, &value)) {
4854 return value;
4855 }
4856 // If \x is not followed by a two-digit hexadecimal, treat it
4857 // as an identity escape.
4858 return 'x';
4859 }
4860 case 'u': {
4861 Advance();
4862 uc32 value;
4863 if (ParseHexEscape(4, &value)) {
4864 return value;
4865 }
4866 // If \u is not followed by a four-digit hexadecimal, treat it
4867 // as an identity escape.
4868 return 'u';
4869 }
4870 default: {
4871 // Extended identity escape. We accept any character that hasn't
4872 // been matched by a more specific case, not just the subset required
4873 // by the ECMAScript specification.
4874 uc32 result = current();
4875 Advance();
4876 return result;
4877 }
4878 }
4879 return 0;
4880}
4881
4882
4883CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4884 ASSERT_EQ(0, *char_class);
4885 uc32 first = current();
4886 if (first == '\\') {
4887 switch (Next()) {
4888 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4889 *char_class = Next();
4890 Advance(2);
4891 return CharacterRange::Singleton(0); // Return dummy value.
4892 }
4893 case kEndMarker:
4894 return ReportError(CStrVector("\\ at end of pattern"));
4895 default:
4896 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4897 return CharacterRange::Singleton(c);
4898 }
4899 } else {
4900 Advance();
4901 return CharacterRange::Singleton(first);
4902 }
4903}
4904
4905
Ben Murdochb0fe1622011-05-05 13:52:32 +01004906static const uc16 kNoCharClass = 0;
4907
4908// Adds range or pre-defined character class to character ranges.
4909// If char_class is not kInvalidClass, it's interpreted as a class
4910// escape (i.e., 's' means whitespace, from '\s').
4911static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4912 uc16 char_class,
4913 CharacterRange range) {
4914 if (char_class != kNoCharClass) {
4915 CharacterRange::AddClassEscape(char_class, ranges);
4916 } else {
4917 ranges->Add(range);
4918 }
4919}
4920
4921
Steve Blocka7e24c12009-10-30 11:49:00 +00004922RegExpTree* RegExpParser::ParseCharacterClass() {
4923 static const char* kUnterminated = "Unterminated character class";
4924 static const char* kRangeOutOfOrder = "Range out of order in character class";
4925
4926 ASSERT_EQ(current(), '[');
4927 Advance();
4928 bool is_negated = false;
4929 if (current() == '^') {
4930 is_negated = true;
4931 Advance();
4932 }
4933 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4934 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004935 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004936 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004937 if (current() == '-') {
4938 Advance();
4939 if (current() == kEndMarker) {
4940 // If we reach the end we break out of the loop and let the
4941 // following code report an error.
4942 break;
4943 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004944 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004945 ranges->Add(CharacterRange::Singleton('-'));
4946 break;
4947 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004948 uc16 char_class_2 = kNoCharClass;
4949 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4950 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4951 // Either end is an escaped character class. Treat the '-' verbatim.
4952 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004953 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004954 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004955 continue;
4956 }
4957 if (first.from() > next.to()) {
4958 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4959 }
4960 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4961 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004962 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004963 }
4964 }
4965 if (!has_more()) {
4966 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4967 }
4968 Advance();
4969 if (ranges->length() == 0) {
4970 ranges->Add(CharacterRange::Everything());
4971 is_negated = !is_negated;
4972 }
4973 return new RegExpCharacterClass(ranges, is_negated);
4974}
4975
4976
4977// ----------------------------------------------------------------------------
4978// The Parser interface.
4979
Steve Blocka7e24c12009-10-30 11:49:00 +00004980ParserMessage::~ParserMessage() {
4981 for (int i = 0; i < args().length(); i++)
4982 DeleteArray(args()[i]);
4983 DeleteArray(args().start());
4984}
4985
4986
4987ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01004988 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00004989}
4990
4991
4992int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01004993 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00004994}
4995
4996
Leon Clarkef7060e22010-06-03 12:02:55 +01004997const char* ScriptDataImpl::Data() {
4998 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00004999}
5000
5001
Leon Clarkee46be812010-01-19 14:06:41 +00005002bool ScriptDataImpl::HasError() {
5003 return has_error();
5004}
5005
5006
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005007void ScriptDataImpl::Initialize() {
5008 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005009 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5010 function_index_ = PreparseDataConstants::kHeaderSize;
5011 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5012 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005013 if (store_.length() > symbol_data_offset) {
5014 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5015 } else {
5016 // Partial preparse causes no symbol information.
5017 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5018 }
5019 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5020 }
5021}
5022
5023
5024int ScriptDataImpl::ReadNumber(byte** source) {
5025 // Reads a number from symbol_data_ in base 128. The most significant
5026 // bit marks that there are more digits.
5027 // If the first byte is 0x80 (kNumberTerminator), it would normally
5028 // represent a leading zero. Since that is useless, and therefore won't
5029 // appear as the first digit of any actual value, it is used to
5030 // mark the end of the input stream.
5031 byte* data = *source;
5032 if (data >= symbol_data_end_) return -1;
5033 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005034 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005035 // End of stream marker.
5036 return -1;
5037 }
5038 int result = input & 0x7f;
5039 data++;
5040 while ((input & 0x80u) != 0) {
5041 if (data >= symbol_data_end_) return -1;
5042 input = *data;
5043 result = (result << 7) | (input & 0x7f);
5044 data++;
5045 }
5046 *source = data;
5047 return result;
5048}
5049
5050
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005051// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005052static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005053 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01005054 ParserRecorder* recorder) {
Steve Block44f0eee2011-05-26 01:26:41 +01005055 Isolate* isolate = Isolate::Current();
5056 V8JavaScriptScanner scanner(isolate->scanner_constants());
Steve Block9fac8402011-05-12 15:51:54 +01005057 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01005058 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005059 if (!preparser::PreParser::PreParseProgram(&scanner,
5060 recorder,
5061 allow_lazy,
5062 stack_limit)) {
Steve Block44f0eee2011-05-26 01:26:41 +01005063 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005064 return NULL;
5065 }
5066
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005067 // Extract the accumulated data from the recorder as a single
5068 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005069 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005070 return new ScriptDataImpl(store);
5071}
5072
5073
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005074// Preparse, but only collect data that is immediately useful,
5075// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005076ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005077 v8::Extension* extension) {
5078 bool allow_lazy = FLAG_lazy && (extension == NULL);
5079 if (!allow_lazy) {
5080 // Partial preparsing is only about lazily compiled functions.
5081 // If we don't allow lazy compilation, the log data will be empty.
5082 return NULL;
5083 }
5084 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005085 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005086}
5087
5088
Ben Murdochb0fe1622011-05-05 13:52:32 +01005089ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005090 v8::Extension* extension) {
5091 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005092 bool allow_lazy = FLAG_lazy && (extension == NULL);
5093 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005094 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005095}
5096
5097
5098bool RegExpParser::ParseRegExp(FlatStringReader* input,
5099 bool multiline,
5100 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005101 ASSERT(result != NULL);
5102 RegExpParser parser(input, &result->error, multiline);
5103 RegExpTree* tree = parser.ParsePattern();
5104 if (parser.failed()) {
5105 ASSERT(tree == NULL);
5106 ASSERT(!result->error.is_null());
5107 } else {
5108 ASSERT(tree != NULL);
5109 ASSERT(result->error.is_null());
5110 result->tree = tree;
5111 int capture_count = parser.captures_started();
5112 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5113 result->contains_anchor = parser.contains_anchor();
5114 result->capture_count = capture_count;
5115 }
5116 return !parser.failed();
5117}
5118
5119
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005120bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005121 ASSERT(info->function() == NULL);
5122 FunctionLiteral* result = NULL;
5123 Handle<Script> script = info->script();
5124 if (info->is_lazy()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005125 Parser parser(script, true, NULL, NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01005126 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00005127 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01005128 bool allow_natives_syntax =
Steve Block44f0eee2011-05-26 01:26:41 +01005129 info->allows_natives_syntax() || FLAG_allow_natives_syntax;
Ben Murdochf87a2032010-10-22 12:50:53 +01005130 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005131 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01005132 if (pre_data != NULL && pre_data->has_error()) {
5133 Scanner::Location loc = pre_data->MessageLocation();
5134 const char* message = pre_data->BuildMessage();
5135 Vector<const char*> args = pre_data->BuildArgs();
5136 parser.ReportMessageAt(loc, message, args);
5137 DeleteArray(message);
5138 for (int i = 0; i < args.length(); i++) {
5139 DeleteArray(args[i]);
5140 }
5141 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01005142 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01005143 } else {
5144 Handle<String> source = Handle<String>(String::cast(script->source()));
Steve Block1e0659c2011-05-24 12:43:12 +01005145 result = parser.ParseProgram(source,
5146 info->is_global(),
5147 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01005148 }
Leon Clarke4515c472010-02-03 11:58:03 +00005149 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005150
5151 info->SetFunction(result);
5152 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005153}
5154
Steve Blocka7e24c12009-10-30 11:49:00 +00005155} } // namespace v8::internal