blob: 90d5c914584a84e31c5107013a7e3b97ca5e5b06 [file] [log] [blame]
Ben Murdoch85b71792012-04-11 18:30:58 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
Ben Murdoch85b71792012-04-11 18:30:58 +010031#include "ast-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "bootstrapper.h"
Ben Murdoch589d6972011-11-30 16:04:58 +000033#include "char-predicates-inl.h"
Steve Block6ded16b2010-05-10 14:33:55 +010034#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010036#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010037#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010038#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080040#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "runtime.h"
Ben Murdoch589d6972011-11-30 16:04:58 +000042#include "scanner-character-streams.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010043#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000044#include "string-stream.h"
45
46namespace v8 {
47namespace internal {
48
Steve Blocka7e24c12009-10-30 11:49:00 +000049// PositionStack is used for on-stack allocation of token positions for
50// new expressions. Please look at ParseNewExpression.
51
52class PositionStack {
53 public:
54 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
55 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
56
57 class Element {
58 public:
59 Element(PositionStack* stack, int value) {
60 previous_ = stack->top();
61 value_ = value;
62 stack->set_top(this);
63 }
64
65 private:
66 Element* previous() { return previous_; }
67 int value() { return value_; }
68 friend class PositionStack;
69 Element* previous_;
70 int value_;
71 };
72
73 bool is_empty() { return top_ == NULL; }
74 int pop() {
75 ASSERT(!is_empty());
76 int result = top_->value();
77 top_ = top_->previous();
78 return result;
79 }
80
81 private:
82 Element* top() { return top_; }
83 void set_top(Element* value) { top_ = value; }
84 Element* top_;
85 bool* ok_;
86};
87
88
Steve Blocka7e24c12009-10-30 11:49:00 +000089RegExpBuilder::RegExpBuilder()
Ben Murdoch8b112d22011-06-08 16:22:53 +010090 : zone_(Isolate::Current()->zone()),
91 pending_empty_(false),
92 characters_(NULL),
93 terms_(),
94 alternatives_()
Steve Blocka7e24c12009-10-30 11:49:00 +000095#ifdef DEBUG
Ben Murdoch8b112d22011-06-08 16:22:53 +010096 , last_added_(ADD_NONE)
Steve Blocka7e24c12009-10-30 11:49:00 +000097#endif
98 {}
99
100
101void RegExpBuilder::FlushCharacters() {
102 pending_empty_ = false;
103 if (characters_ != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100104 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
Steve Blocka7e24c12009-10-30 11:49:00 +0000105 characters_ = NULL;
106 text_.Add(atom);
107 LAST(ADD_ATOM);
108 }
109}
110
111
112void RegExpBuilder::FlushText() {
113 FlushCharacters();
114 int num_text = text_.length();
115 if (num_text == 0) {
116 return;
117 } else if (num_text == 1) {
118 terms_.Add(text_.last());
119 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100120 RegExpText* text = new(zone()) RegExpText();
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 for (int i = 0; i < num_text; i++)
122 text_.Get(i)->AppendToText(text);
123 terms_.Add(text);
124 }
125 text_.Clear();
126}
127
128
129void RegExpBuilder::AddCharacter(uc16 c) {
130 pending_empty_ = false;
131 if (characters_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000132 characters_ = new(zone()) ZoneList<uc16>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000133 }
134 characters_->Add(c);
135 LAST(ADD_CHAR);
136}
137
138
139void RegExpBuilder::AddEmpty() {
140 pending_empty_ = true;
141}
142
143
144void RegExpBuilder::AddAtom(RegExpTree* term) {
145 if (term->IsEmpty()) {
146 AddEmpty();
147 return;
148 }
149 if (term->IsTextElement()) {
150 FlushCharacters();
151 text_.Add(term);
152 } else {
153 FlushText();
154 terms_.Add(term);
155 }
156 LAST(ADD_ATOM);
157}
158
159
160void RegExpBuilder::AddAssertion(RegExpTree* assert) {
161 FlushText();
162 terms_.Add(assert);
163 LAST(ADD_ASSERT);
164}
165
166
167void RegExpBuilder::NewAlternative() {
168 FlushTerms();
169}
170
171
172void RegExpBuilder::FlushTerms() {
173 FlushText();
174 int num_terms = terms_.length();
175 RegExpTree* alternative;
176 if (num_terms == 0) {
177 alternative = RegExpEmpty::GetInstance();
178 } else if (num_terms == 1) {
179 alternative = terms_.last();
180 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100181 alternative = new(zone()) RegExpAlternative(terms_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 }
183 alternatives_.Add(alternative);
184 terms_.Clear();
185 LAST(ADD_NONE);
186}
187
188
189RegExpTree* RegExpBuilder::ToRegExp() {
190 FlushTerms();
191 int num_alternatives = alternatives_.length();
192 if (num_alternatives == 0) {
193 return RegExpEmpty::GetInstance();
194 }
195 if (num_alternatives == 1) {
196 return alternatives_.last();
197 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100198 return new(zone()) RegExpDisjunction(alternatives_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000199}
200
201
Leon Clarkee46be812010-01-19 14:06:41 +0000202void RegExpBuilder::AddQuantifierToAtom(int min,
203 int max,
204 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (pending_empty_) {
206 pending_empty_ = false;
207 return;
208 }
209 RegExpTree* atom;
210 if (characters_ != NULL) {
211 ASSERT(last_added_ == ADD_CHAR);
212 // Last atom was character.
213 Vector<const uc16> char_vector = characters_->ToConstVector();
214 int num_chars = char_vector.length();
215 if (num_chars > 1) {
216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100217 text_.Add(new(zone()) RegExpAtom(prefix));
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219 }
220 characters_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100221 atom = new(zone()) RegExpAtom(char_vector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000222 FlushText();
223 } else if (text_.length() > 0) {
224 ASSERT(last_added_ == ADD_ATOM);
225 atom = text_.RemoveLast();
226 FlushText();
227 } else if (terms_.length() > 0) {
228 ASSERT(last_added_ == ADD_ATOM);
229 atom = terms_.RemoveLast();
230 if (atom->max_match() == 0) {
231 // Guaranteed to only match an empty string.
232 LAST(ADD_TERM);
233 if (min == 0) {
234 return;
235 }
236 terms_.Add(atom);
237 return;
238 }
239 } else {
240 // Only call immediately after adding an atom or character!
241 UNREACHABLE();
242 return;
243 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100244 terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 LAST(ADD_TERM);
246}
247
248
Steve Block9fac8402011-05-12 15:51:54 +0100249Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800250 // Length of symbol cache is the number of identified symbols.
251 // If we are larger than that, or negative, it's not a cached symbol.
252 // This might also happen if there is no preparser symbol data, even
253 // if there is some preparser data.
254 if (static_cast<unsigned>(symbol_id)
255 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100256 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100257 return isolate()->factory()->LookupAsciiSymbol(
258 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100259 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100260 return isolate()->factory()->LookupTwoByteSymbol(
Ben Murdoch85b71792012-04-11 18:30:58 +0100261 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(
Ben Murdoch85b71792012-04-11 18:30:58 +0100282 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
Ben Murdoch85b71792012-04-11 18:30:58 +0100410Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100411 Scope* result = new(zone()) Scope(parent, type);
Ben Murdoch85b71792012-04-11 18:30:58 +0100412 result->Initialize(inside_with);
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 return result;
414}
415
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000416
Steve Blocka7e24c12009-10-30 11:49:00 +0000417// ----------------------------------------------------------------------------
418// Target is a support class to facilitate manipulation of the
419// Parser's target_stack_ (the stack of potential 'break' and
420// 'continue' statement targets). Upon construction, a new target is
421// added; it is removed upon destruction.
422
423class Target BASE_EMBEDDED {
424 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800425 Target(Target** variable, AstNode* node)
426 : variable_(variable), node_(node), previous_(*variable) {
427 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 }
429
430 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800431 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 }
433
434 Target* previous() { return previous_; }
435 AstNode* node() { return node_; }
436
437 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800438 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 AstNode* node_;
440 Target* previous_;
441};
442
443
444class TargetScope BASE_EMBEDDED {
445 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800446 explicit TargetScope(Target** variable)
447 : variable_(variable), previous_(*variable) {
448 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 }
450
451 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800452 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 }
454
455 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800456 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 Target* previous_;
458};
459
460
461// ----------------------------------------------------------------------------
Ben Murdoch85b71792012-04-11 18:30:58 +0100462// LexicalScope is a support class to facilitate manipulation of the
463// Parser's scope stack. The constructor sets the parser's top scope
464// to the incoming scope, and the destructor resets it.
465//
466// Additionally, it stores transient information used during parsing.
467// These scopes are not kept around after parsing or referenced by syntax
468// trees so they can be stack-allocated and hence used by the pre-parser.
Steve Blocka7e24c12009-10-30 11:49:00 +0000469
Ben Murdoch85b71792012-04-11 18:30:58 +0100470class LexicalScope BASE_EMBEDDED {
Steve Blocka7e24c12009-10-30 11:49:00 +0000471 public:
Ben Murdoch85b71792012-04-11 18:30:58 +0100472 LexicalScope(Parser* parser, Scope* scope, Isolate* isolate);
473 ~LexicalScope();
474
475 int NextMaterializedLiteralIndex() {
476 int next_index =
477 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
478 materialized_literal_count_++;
479 return next_index;
480 }
481 int materialized_literal_count() { return materialized_literal_count_; }
482
483 void SetThisPropertyAssignmentInfo(
484 bool only_simple_this_property_assignments,
485 Handle<FixedArray> this_property_assignments) {
486 only_simple_this_property_assignments_ =
487 only_simple_this_property_assignments;
488 this_property_assignments_ = this_property_assignments;
489 }
490 bool only_simple_this_property_assignments() {
491 return only_simple_this_property_assignments_;
492 }
493 Handle<FixedArray> this_property_assignments() {
494 return this_property_assignments_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000495 }
496
Ben Murdoch85b71792012-04-11 18:30:58 +0100497 void AddProperty() { expected_property_count_++; }
498 int expected_property_count() { return expected_property_count_; }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000499
500 private:
Ben Murdoch85b71792012-04-11 18:30:58 +0100501 // Captures the number of literals that need materialization in the
502 // function. Includes regexp literals, and boilerplate for object
503 // and array literals.
504 int materialized_literal_count_;
505
506 // Properties count estimation.
507 int expected_property_count_;
508
509 // Keeps track of assignments to properties of this. Used for
510 // optimizing constructors.
511 bool only_simple_this_property_assignments_;
512 Handle<FixedArray> this_property_assignments_;
513
514 // Bookkeeping
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000515 Parser* parser_;
Ben Murdoch85b71792012-04-11 18:30:58 +0100516 // Previous values
517 LexicalScope* lexical_scope_parent_;
518 Scope* previous_scope_;
519 int previous_with_nesting_level_;
520 unsigned previous_ast_node_id_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000521};
522
523
Ben Murdoch85b71792012-04-11 18:30:58 +0100524LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
525 : materialized_literal_count_(0),
526 expected_property_count_(0),
527 only_simple_this_property_assignments_(false),
528 this_property_assignments_(isolate->factory()->empty_fixed_array()),
529 parser_(parser),
530 lexical_scope_parent_(parser->lexical_scope_),
531 previous_scope_(parser->top_scope_),
532 previous_with_nesting_level_(parser->with_nesting_level_),
533 previous_ast_node_id_(isolate->ast_node_id()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100534 parser->top_scope_ = scope;
Ben Murdoch85b71792012-04-11 18:30:58 +0100535 parser->lexical_scope_ = this;
536 parser->with_nesting_level_ = 0;
Ben Murdoch589d6972011-11-30 16:04:58 +0000537 isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
Steve Block44f0eee2011-05-26 01:26:41 +0100538}
539
540
Ben Murdoch85b71792012-04-11 18:30:58 +0100541LexicalScope::~LexicalScope() {
542 parser_->top_scope_ = previous_scope_;
543 parser_->lexical_scope_ = lexical_scope_parent_;
544 parser_->with_nesting_level_ = previous_with_nesting_level_;
545 parser_->isolate()->set_ast_node_id(previous_ast_node_id_);
Steve Block44f0eee2011-05-26 01:26:41 +0100546}
547
548
Steve Blocka7e24c12009-10-30 11:49:00 +0000549// ----------------------------------------------------------------------------
550// The CHECK_OK macro is a convenient macro to enforce error
551// handling for functions that may fail (by returning !*ok).
552//
553// CAUTION: This macro appends extra statements after a call,
554// thus it must never be used where only a single statement
555// is correct (e.g. an if statement branch w/o braces)!
556
557#define CHECK_OK ok); \
558 if (!*ok) return NULL; \
559 ((void)0
560#define DUMMY ) // to make indentation work
561#undef DUMMY
562
563#define CHECK_FAILED /**/); \
564 if (failed_) return NULL; \
565 ((void)0
566#define DUMMY ) // to make indentation work
567#undef DUMMY
568
569// ----------------------------------------------------------------------------
570// Implementation of Parser
571
572Parser::Parser(Handle<Script> script,
Ben Murdoch85b71792012-04-11 18:30:58 +0100573 bool allow_natives_syntax,
Steve Blocka7e24c12009-10-30 11:49:00 +0000574 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000575 ScriptDataImpl* pre_data)
Steve Block44f0eee2011-05-26 01:26:41 +0100576 : isolate_(script->GetIsolate()),
577 symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800578 script_(script),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100579 scanner_(isolate_->unicode_cache()),
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 top_scope_(NULL),
Ben Murdoch85b71792012-04-11 18:30:58 +0100581 with_nesting_level_(0),
582 lexical_scope_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 target_stack_(NULL),
Ben Murdoch85b71792012-04-11 18:30:58 +0100584 allow_natives_syntax_(allow_natives_syntax),
Steve Blocka7e24c12009-10-30 11:49:00 +0000585 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100586 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100587 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100588 stack_overflow_(false),
Ben Murdoch85b71792012-04-11 18:30:58 +0100589 parenthesized_function_(false),
590 harmony_block_scoping_(false) {
591 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000592}
593
594
Ben Murdoch85b71792012-04-11 18:30:58 +0100595FunctionLiteral* Parser::ParseProgram(Handle<String> source,
596 bool in_global_context,
597 StrictModeFlag strict_mode) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000598 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000599
Steve Block44f0eee2011-05-26 01:26:41 +0100600 HistogramTimerScope timer(isolate()->counters()->parse());
601 isolate()->counters()->total_parse_size()->Increment(source->length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000602 fni_ = new(zone()) FuncNameInferrer(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000603
604 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100605 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100606 if (source->IsExternalTwoByteString()) {
607 // Notice that the stream is destroyed at the end of the branch block.
608 // The last line of the blocks can't be moved outside, even though they're
609 // identical calls.
Ben Murdoch85b71792012-04-11 18:30:58 +0100610 ExternalTwoByteStringUC16CharacterStream stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100611 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100612 scanner_.Initialize(&stream);
Ben Murdoch85b71792012-04-11 18:30:58 +0100613 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100614 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +0100615 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100616 scanner_.Initialize(&stream);
Ben Murdoch85b71792012-04-11 18:30:58 +0100617 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618 }
619}
620
621
Ben Murdoch85b71792012-04-11 18:30:58 +0100622FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
623 bool in_global_context,
624 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100625 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000626 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100627 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000628
629 // Compute the parsing mode.
Ben Murdoch85b71792012-04-11 18:30:58 +0100630 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
Steve Blocka7e24c12009-10-30 11:49:00 +0000631 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
632
Ben Murdoch85b71792012-04-11 18:30:58 +0100633 Scope::Type type =
634 in_global_context
635 ? Scope::GLOBAL_SCOPE
636 : Scope::EVAL_SCOPE;
Steve Block44f0eee2011-05-26 01:26:41 +0100637 Handle<String> no_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000638
639 FunctionLiteral* result = NULL;
Ben Murdoch85b71792012-04-11 18:30:58 +0100640 { Scope* scope = NewScope(top_scope_, type, inside_with());
641 LexicalScope lexical_scope(this, scope, isolate());
642 if (strict_mode == kStrictMode) {
643 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100644 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000645 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000646 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100647 int beg_loc = scanner().location().beg_pos;
Ben Murdoch85b71792012-04-11 18:30:58 +0100648 ParseSourceElements(body, Token::EOS, &ok);
649 if (ok && top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100650 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
651 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000652
Ben Murdoch85b71792012-04-11 18:30:58 +0100653 if (ok && harmony_block_scoping_) {
654 CheckConflictingVarDeclarations(scope, &ok);
Ben Murdoch589d6972011-11-30 16:04:58 +0000655 }
656
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 if (ok) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100658 result = new(zone()) FunctionLiteral(
659 isolate(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000660 no_name,
661 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800662 body,
Ben Murdoch85b71792012-04-11 18:30:58 +0100663 lexical_scope.materialized_literal_count(),
664 lexical_scope.expected_property_count(),
665 lexical_scope.only_simple_this_property_assignments(),
666 lexical_scope.this_property_assignments(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000667 0,
Ben Murdoch85b71792012-04-11 18:30:58 +0100668 0,
669 source->length(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000670 FunctionLiteral::ANONYMOUS_EXPRESSION,
Ben Murdoch85b71792012-04-11 18:30:58 +0100671 false); // Does not have duplicate parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 } else if (stack_overflow_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100673 isolate()->StackOverflow();
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 }
675 }
676
677 // Make sure the target stack is empty.
678 ASSERT(target_stack_ == NULL);
679
680 // If there was a syntax error we have to get rid of the AST
681 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100682 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 return result;
684}
685
Steve Block44f0eee2011-05-26 01:26:41 +0100686FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000687 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Block44f0eee2011-05-26 01:26:41 +0100688 HistogramTimerScope timer(isolate()->counters()->parse_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100689 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100690 isolate()->counters()->total_parse_size()->Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000691
Steve Block44f0eee2011-05-26 01:26:41 +0100692 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100693 // Initialize parser state.
694 source->TryFlatten();
695 if (source->IsExternalTwoByteString()) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100696 ExternalTwoByteStringUC16CharacterStream stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100697 Handle<ExternalTwoByteString>::cast(source),
Steve Block44f0eee2011-05-26 01:26:41 +0100698 shared_info->start_position(),
699 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100700 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
701 return result;
702 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +0100703 GenericStringUC16CharacterStream stream(source,
704 shared_info->start_position(),
705 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100706 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
707 return result;
708 }
709}
710
711
Steve Block44f0eee2011-05-26 01:26:41 +0100712FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
Ben Murdoch85b71792012-04-11 18:30:58 +0100713 UC16CharacterStream* source,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100714 ZoneScope* zone_scope) {
Steve Block44f0eee2011-05-26 01:26:41 +0100715 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Steve Block9fac8402011-05-12 15:51:54 +0100716 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717 ASSERT(target_stack_ == NULL);
718
Steve Block44f0eee2011-05-26 01:26:41 +0100719 Handle<String> name(String::cast(shared_info->name()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000720 fni_ = new(zone()) FuncNameInferrer(isolate());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100721 fni_->PushEnclosingName(name);
722
Steve Blocka7e24c12009-10-30 11:49:00 +0000723 mode_ = PARSE_EAGERLY;
724
725 // Place holder for the result.
726 FunctionLiteral* result = NULL;
727
728 {
729 // Parse the function literal.
Ben Murdoch85b71792012-04-11 18:30:58 +0100730 Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
Steve Block44f0eee2011-05-26 01:26:41 +0100731 if (!info->closure().is_null()) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100732 scope = Scope::DeserializeScopeChain(info, scope);
Steve Block44f0eee2011-05-26 01:26:41 +0100733 }
Ben Murdoch85b71792012-04-11 18:30:58 +0100734 LexicalScope lexical_scope(this, scope, isolate());
735
736 if (shared_info->strict_mode()) {
737 top_scope_->EnableStrictMode();
738 }
739
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000740 FunctionLiteral::Type type = shared_info->is_expression()
741 ? (shared_info->is_anonymous()
742 ? FunctionLiteral::ANONYMOUS_EXPRESSION
743 : FunctionLiteral::NAMED_EXPRESSION)
744 : FunctionLiteral::DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100746 result = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000747 false, // Strict mode name already checked.
748 RelocInfo::kNoPosition,
749 type,
750 &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000751 // Make sure the results agree.
752 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000753 }
754
755 // Make sure the target stack is empty.
756 ASSERT(target_stack_ == NULL);
757
758 // If there was a stack overflow we have to get rid of AST and it is
759 // not safe to do before scope has been deleted.
760 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100761 zone_scope->DeleteOnExit();
Steve Block44f0eee2011-05-26 01:26:41 +0100762 if (stack_overflow_) isolate()->StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100763 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100764 Handle<String> inferred_name(shared_info->inferred_name());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100765 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000766 }
767 return result;
768}
769
Ben Murdochf87a2032010-10-22 12:50:53 +0100770
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800771Handle<String> Parser::GetSymbol(bool* ok) {
772 int symbol_id = -1;
773 if (pre_data() != NULL) {
774 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000775 }
Steve Block9fac8402011-05-12 15:51:54 +0100776 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000777}
Steve Blocka7e24c12009-10-30 11:49:00 +0000778
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800779
Steve Blocka7e24c12009-10-30 11:49:00 +0000780void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100781 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000782 ReportMessageAt(source_location, type, args);
783}
784
785
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800786void Parser::ReportMessageAt(Scanner::Location source_location,
787 const char* type,
788 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000789 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100790 source_location.beg_pos,
791 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100792 Factory* factory = isolate()->factory();
793 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000794 for (int i = 0; i < args.length(); i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100795 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100796 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000797 }
Steve Block44f0eee2011-05-26 01:26:41 +0100798 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
799 Handle<Object> result = factory->NewSyntaxError(type, array);
800 isolate()->Throw(*result, &location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000801}
802
803
Ben Murdochb8e0da22011-05-16 14:20:40 +0100804void Parser::ReportMessageAt(Scanner::Location source_location,
805 const char* type,
806 Vector<Handle<String> > args) {
807 MessageLocation location(script_,
808 source_location.beg_pos,
809 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100810 Factory* factory = isolate()->factory();
811 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100812 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100813 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100814 }
Steve Block44f0eee2011-05-26 01:26:41 +0100815 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
816 Handle<Object> result = factory->NewSyntaxError(type, array);
817 isolate()->Throw(*result, &location);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100818}
819
Ben Murdoch85b71792012-04-11 18:30:58 +0100820void Parser::SetHarmonyBlockScoping(bool block_scoping) {
821 scanner().SetHarmonyBlockScoping(block_scoping);
822 harmony_block_scoping_ = block_scoping;
823}
Ben Murdochb8e0da22011-05-16 14:20:40 +0100824
Steve Blocka7e24c12009-10-30 11:49:00 +0000825// Base class containing common code for the different finder classes used by
826// the parser.
827class ParserFinder {
828 protected:
829 ParserFinder() {}
830 static Assignment* AsAssignment(Statement* stat) {
831 if (stat == NULL) return NULL;
832 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
833 if (exp_stat == NULL) return NULL;
834 return exp_stat->expression()->AsAssignment();
835 }
836};
837
838
839// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000840// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000841class InitializationBlockFinder : public ParserFinder {
842 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000843 // We find and mark the initialization blocks in top level
844 // non-looping code only. This is because the optimization prevents
845 // reuse of the map transitions, so it should be used only for code
846 // that will only be run once.
847 InitializationBlockFinder(Scope* top_scope, Target* target)
848 : enabled_(top_scope->DeclarationScope()->is_global_scope() &&
849 !IsLoopTarget(target)),
850 first_in_block_(NULL),
851 last_in_block_(NULL),
852 block_size_(0) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000853
854 ~InitializationBlockFinder() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000855 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 if (InBlock()) EndBlock();
857 }
858
859 void Update(Statement* stat) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000860 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 Assignment* assignment = AsAssignment(stat);
862 if (InBlock()) {
863 if (BlockContinues(assignment)) {
864 UpdateBlock(assignment);
865 } else {
866 EndBlock();
867 }
868 }
869 if (!InBlock() && (assignment != NULL) &&
870 (assignment->op() == Token::ASSIGN)) {
871 StartBlock(assignment);
872 }
873 }
874
875 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800876 // The minimum number of contiguous assignment that will
877 // be treated as an initialization block. Benchmarks show that
878 // the overhead exceeds the savings below this limit.
879 static const int kMinInitializationBlock = 3;
880
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000881 static bool IsLoopTarget(Target* target) {
882 while (target != NULL) {
883 if (target->node()->AsIterationStatement() != NULL) return true;
884 target = target->previous();
885 }
886 return false;
887 }
888
Steve Blocka7e24c12009-10-30 11:49:00 +0000889 // Returns true if the expressions appear to denote the same object.
890 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000891 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000892 static bool SameObject(Expression* e1, Expression* e2) {
893 VariableProxy* v1 = e1->AsVariableProxy();
894 VariableProxy* v2 = e2->AsVariableProxy();
895 if (v1 != NULL && v2 != NULL) {
896 return v1->name()->Equals(*v2->name());
897 }
898 Property* p1 = e1->AsProperty();
899 Property* p2 = e2->AsProperty();
900 if ((p1 == NULL) || (p2 == NULL)) return false;
901 Literal* key1 = p1->key()->AsLiteral();
902 Literal* key2 = p2->key()->AsLiteral();
903 if ((key1 == NULL) || (key2 == NULL)) return false;
904 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
905 return false;
906 }
907 String* name1 = String::cast(*key1->handle());
908 String* name2 = String::cast(*key2->handle());
909 if (!name1->Equals(name2)) return false;
910 return SameObject(p1->obj(), p2->obj());
911 }
912
913 // Returns true if the expressions appear to denote different properties
914 // of the same object.
915 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
916 Property* p1 = e1->AsProperty();
917 Property* p2 = e2->AsProperty();
918 if ((p1 == NULL) || (p2 == NULL)) return false;
919 return SameObject(p1->obj(), p2->obj());
920 }
921
922 bool BlockContinues(Assignment* assignment) {
923 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
924 if (assignment->op() != Token::ASSIGN) return false;
925 return PropertyOfSameObject(first_in_block_->target(),
926 assignment->target());
927 }
928
929 void StartBlock(Assignment* assignment) {
930 first_in_block_ = assignment;
931 last_in_block_ = assignment;
932 block_size_ = 1;
933 }
934
935 void UpdateBlock(Assignment* assignment) {
936 last_in_block_ = assignment;
937 ++block_size_;
938 }
939
940 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800941 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000942 first_in_block_->mark_block_start();
943 last_in_block_->mark_block_end();
944 }
945 last_in_block_ = first_in_block_ = NULL;
946 block_size_ = 0;
947 }
948
949 bool InBlock() { return first_in_block_ != NULL; }
950
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000951 const bool enabled_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000952 Assignment* first_in_block_;
953 Assignment* last_in_block_;
954 int block_size_;
955
956 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
957};
958
959
Ben Murdoch85b71792012-04-11 18:30:58 +0100960// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
Steve Blocka7e24c12009-10-30 11:49:00 +0000961// this.x = ...;, where x is a named property. It also determines whether a
962// function contains only assignments of this type.
Ben Murdoch85b71792012-04-11 18:30:58 +0100963class ThisNamedPropertyAssigmentFinder : public ParserFinder {
Steve Blocka7e24c12009-10-30 11:49:00 +0000964 public:
Ben Murdoch85b71792012-04-11 18:30:58 +0100965 explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate)
Steve Block44f0eee2011-05-26 01:26:41 +0100966 : isolate_(isolate),
967 only_simple_this_property_assignments_(true),
Ben Murdoch85b71792012-04-11 18:30:58 +0100968 names_(NULL),
969 assigned_arguments_(NULL),
970 assigned_constants_(NULL) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000971
972 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000973 // Bail out if function already has property assignment that are
974 // not simple this property assignments.
975 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000976 return;
977 }
978
979 // Check whether this statement is of the form this.x = ...;
980 Assignment* assignment = AsAssignment(stat);
981 if (IsThisPropertyAssignment(assignment)) {
982 HandleThisPropertyAssignment(scope, assignment);
983 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000984 only_simple_this_property_assignments_ = false;
985 }
986 }
987
Steve Blocka7e24c12009-10-30 11:49:00 +0000988 // Returns whether only statements of the form this.x = y; where y is either a
989 // constant or a function argument was encountered.
990 bool only_simple_this_property_assignments() {
991 return only_simple_this_property_assignments_;
992 }
993
994 // Returns a fixed array containing three elements for each assignment of the
995 // form this.x = y;
996 Handle<FixedArray> GetThisPropertyAssignments() {
Ben Murdoch85b71792012-04-11 18:30:58 +0100997 if (names_ == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100998 return isolate_->factory()->empty_fixed_array();
Steve Blocka7e24c12009-10-30 11:49:00 +0000999 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001000 ASSERT(names_ != NULL);
1001 ASSERT(assigned_arguments_ != NULL);
1002 ASSERT_EQ(names_->length(), assigned_arguments_->length());
1003 ASSERT_EQ(names_->length(), assigned_constants_->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001004 Handle<FixedArray> assignments =
Ben Murdoch85b71792012-04-11 18:30:58 +01001005 isolate_->factory()->NewFixedArray(names_->length() * 3);
1006 for (int i = 0; i < names_->length(); i++) {
1007 assignments->set(i * 3, *names_->at(i));
1008 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
1009 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001010 }
1011 return assignments;
1012 }
1013
1014 private:
1015 bool IsThisPropertyAssignment(Assignment* assignment) {
1016 if (assignment != NULL) {
1017 Property* property = assignment->target()->AsProperty();
1018 return assignment->op() == Token::ASSIGN
1019 && property != NULL
1020 && property->obj()->AsVariableProxy() != NULL
1021 && property->obj()->AsVariableProxy()->is_this();
1022 }
1023 return false;
1024 }
1025
1026 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +01001027 // Check that the property assigned to is a named property, which is not
1028 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 Property* property = assignment->target()->AsProperty();
1030 ASSERT(property != NULL);
1031 Literal* literal = property->key()->AsLiteral();
1032 uint32_t dummy;
1033 if (literal != NULL &&
1034 literal->handle()->IsString() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001035 !String::cast(*(literal->handle()))->Equals(
1036 isolate_->heap()->Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001037 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1038 Handle<String> key = Handle<String>::cast(literal->handle());
1039
1040 // Check whether the value assigned is either a constant or matches the
1041 // name of one of the arguments to the function.
1042 if (assignment->value()->AsLiteral() != NULL) {
1043 // Constant assigned.
1044 Literal* literal = assignment->value()->AsLiteral();
1045 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001046 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001047 } else if (assignment->value()->AsVariableProxy() != NULL) {
1048 // Variable assigned.
1049 Handle<String> name =
1050 assignment->value()->AsVariableProxy()->name();
1051 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001052 for (int i = 0; i < scope->num_parameters(); i++) {
1053 if (*scope->parameter(i)->name() == *name) {
1054 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001055 AssignmentFromParameter(key, i);
1056 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001057 }
1058 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001059 }
1060 }
Steve Blockd0582a62009-12-15 09:54:21 +00001061 // It is not a simple "this.x = value;" assignment with a constant
1062 // or parameter value.
1063 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001064 }
1065
1066 void AssignmentFromParameter(Handle<String> name, int index) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001067 EnsureAllocation();
1068 names_->Add(name);
1069 assigned_arguments_->Add(index);
1070 assigned_constants_->Add(isolate_->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001071 }
1072
1073 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001074 EnsureAllocation();
1075 names_->Add(name);
1076 assigned_arguments_->Add(-1);
1077 assigned_constants_->Add(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001078 }
1079
Steve Blockd0582a62009-12-15 09:54:21 +00001080 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001081 // The this assignment is not a simple one.
1082 only_simple_this_property_assignments_ = false;
1083 }
1084
Ben Murdoch85b71792012-04-11 18:30:58 +01001085 void EnsureAllocation() {
1086 if (names_ == NULL) {
1087 ASSERT(assigned_arguments_ == NULL);
1088 ASSERT(assigned_constants_ == NULL);
1089 Zone* zone = isolate_->zone();
1090 names_ = new(zone) ZoneStringList(4);
1091 assigned_arguments_ = new(zone) ZoneList<int>(4);
1092 assigned_constants_ = new(zone) ZoneObjectList(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001093 }
1094 }
1095
Steve Block44f0eee2011-05-26 01:26:41 +01001096 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001097 bool only_simple_this_property_assignments_;
Ben Murdoch85b71792012-04-11 18:30:58 +01001098 ZoneStringList* names_;
1099 ZoneList<int>* assigned_arguments_;
1100 ZoneObjectList* assigned_constants_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001101};
1102
1103
Ben Murdoch85b71792012-04-11 18:30:58 +01001104Statement* Parser::ParseSourceElement(ZoneStringList* labels,
1105 bool* ok) {
1106 if (peek() == Token::FUNCTION) {
1107 // FunctionDeclaration is only allowed in the context of SourceElements
1108 // (Ecma 262 5th Edition, clause 14):
1109 // SourceElement:
1110 // Statement
1111 // FunctionDeclaration
1112 // Common language extension is to allow function declaration in place
1113 // of any statement. This language extension is disabled in strict mode.
1114 return ParseFunctionDeclaration(ok);
1115 } else if (peek() == Token::LET) {
1116 return ParseVariableStatement(kSourceElement, ok);
1117 } else {
1118 return ParseStatement(labels, ok);
1119 }
1120}
1121
1122
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001123void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001124 int end_token,
1125 bool* ok) {
1126 // SourceElements ::
Ben Murdoch85b71792012-04-11 18:30:58 +01001127 // (Statement)* <end_token>
Steve Blocka7e24c12009-10-30 11:49:00 +00001128
1129 // Allocate a target stack to use for this set of source
1130 // elements. This way, all scripts and functions get their own
1131 // target stack thus avoiding illegal breaks and continues across
1132 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001133 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001134
1135 ASSERT(processor != NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001136 InitializationBlockFinder block_finder(top_scope_, target_stack_);
Ben Murdoch85b71792012-04-11 18:30:58 +01001137 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
Steve Block1e0659c2011-05-24 12:43:12 +01001138 bool directive_prologue = true; // Parsing directive prologue.
1139
Steve Blocka7e24c12009-10-30 11:49:00 +00001140 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001141 if (directive_prologue && peek() != Token::STRING) {
1142 directive_prologue = false;
1143 }
1144
1145 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoch85b71792012-04-11 18:30:58 +01001146 Statement* stat = ParseSourceElement(NULL, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001147 if (stat == NULL || stat->IsEmpty()) {
1148 directive_prologue = false; // End of directive prologue.
1149 continue;
1150 }
1151
1152 if (directive_prologue) {
1153 // A shot at a directive.
Ben Murdoch85b71792012-04-11 18:30:58 +01001154 ExpressionStatement *e_stat;
1155 Literal *literal;
Steve Block1e0659c2011-05-24 12:43:12 +01001156 // Still processing directive prologue?
1157 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1158 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1159 literal->handle()->IsString()) {
1160 Handle<String> directive = Handle<String>::cast(literal->handle());
1161
1162 // Check "use strict" directive (ES5 14.1).
Ben Murdoch85b71792012-04-11 18:30:58 +01001163 if (!top_scope_->is_strict_mode() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001164 directive->Equals(isolate()->heap()->use_strict()) &&
Steve Block1e0659c2011-05-24 12:43:12 +01001165 token_loc.end_pos - token_loc.beg_pos ==
Steve Block44f0eee2011-05-26 01:26:41 +01001166 isolate()->heap()->use_strict()->length() + 2) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001167 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +01001168 // "use strict" is the only directive for now.
1169 directive_prologue = false;
1170 }
1171 } else {
1172 // End of the directive prologue.
1173 directive_prologue = false;
1174 }
1175 }
1176
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001177 block_finder.Update(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001178 // Find and mark all assignments to named properties in this (this.x =)
1179 if (top_scope_->is_function_scope()) {
1180 this_property_assignment_finder.Update(top_scope_, stat);
1181 }
1182 processor->Add(stat);
1183 }
1184
1185 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001186 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001187 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001188 this_property_assignment_finder.only_simple_this_property_assignments()
1189 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001190 if (only_simple_this_property_assignments) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001191 lexical_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001192 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001193 this_property_assignment_finder.GetThisPropertyAssignments());
1194 }
1195 }
1196 return 0;
1197}
1198
1199
1200Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1201 // Statement ::
1202 // Block
1203 // VariableStatement
1204 // EmptyStatement
1205 // ExpressionStatement
1206 // IfStatement
1207 // IterationStatement
1208 // ContinueStatement
1209 // BreakStatement
1210 // ReturnStatement
1211 // WithStatement
1212 // LabelledStatement
1213 // SwitchStatement
1214 // ThrowStatement
1215 // TryStatement
1216 // DebuggerStatement
1217
1218 // Note: Since labels can only be used by 'break' and 'continue'
1219 // statements, which themselves are only valid within blocks,
1220 // iterations or 'switch' statements (i.e., BreakableStatements),
1221 // labels can be simply ignored in all other cases; except for
1222 // trivial labeled break statements 'label: break label' which is
1223 // parsed into an empty statement.
1224
1225 // Keep the source position of the statement
1226 int statement_pos = scanner().peek_location().beg_pos;
1227 Statement* stmt = NULL;
1228 switch (peek()) {
1229 case Token::LBRACE:
1230 return ParseBlock(labels, ok);
1231
1232 case Token::CONST: // fall through
1233 case Token::VAR:
Ben Murdoch85b71792012-04-11 18:30:58 +01001234 stmt = ParseVariableStatement(kStatement, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001235 break;
1236
1237 case Token::SEMICOLON:
1238 Next();
Ben Murdoch85b71792012-04-11 18:30:58 +01001239 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001240
1241 case Token::IF:
1242 stmt = ParseIfStatement(labels, ok);
1243 break;
1244
1245 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001246 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001247 break;
1248
1249 case Token::WHILE:
1250 stmt = ParseWhileStatement(labels, ok);
1251 break;
1252
1253 case Token::FOR:
1254 stmt = ParseForStatement(labels, ok);
1255 break;
1256
1257 case Token::CONTINUE:
1258 stmt = ParseContinueStatement(ok);
1259 break;
1260
1261 case Token::BREAK:
1262 stmt = ParseBreakStatement(labels, ok);
1263 break;
1264
1265 case Token::RETURN:
1266 stmt = ParseReturnStatement(ok);
1267 break;
1268
1269 case Token::WITH:
1270 stmt = ParseWithStatement(labels, ok);
1271 break;
1272
1273 case Token::SWITCH:
1274 stmt = ParseSwitchStatement(labels, ok);
1275 break;
1276
1277 case Token::THROW:
1278 stmt = ParseThrowStatement(ok);
1279 break;
1280
1281 case Token::TRY: {
1282 // NOTE: It is somewhat complicated to have labels on
1283 // try-statements. When breaking out of a try-finally statement,
1284 // one must take great care not to treat it as a
1285 // fall-through. It is much easier just to wrap the entire
1286 // try-statement in a statement block and put the labels there
Ben Murdoch85b71792012-04-11 18:30:58 +01001287 Block* result = new(zone()) Block(isolate(), labels, 1, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001288 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 TryStatement* statement = ParseTryStatement(CHECK_OK);
1290 if (statement) {
1291 statement->set_statement_pos(statement_pos);
1292 }
1293 if (result) result->AddStatement(statement);
1294 return result;
1295 }
1296
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001297 case Token::FUNCTION: {
Ben Murdoch85b71792012-04-11 18:30:58 +01001298 // In strict mode, FunctionDeclaration is only allowed in the context
1299 // of SourceElements.
1300 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001301 ReportMessageAt(scanner().peek_location(), "strict_function",
1302 Vector<const char*>::empty());
1303 *ok = false;
1304 return NULL;
1305 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001306 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001307 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001308
Steve Blocka7e24c12009-10-30 11:49:00 +00001309 case Token::DEBUGGER:
1310 stmt = ParseDebuggerStatement(ok);
1311 break;
1312
1313 default:
1314 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1315 }
1316
1317 // Store the source position of the statement
1318 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1319 return stmt;
1320}
1321
1322
Ben Murdoch85b71792012-04-11 18:30:58 +01001323VariableProxy* Parser::Declare(Handle<String> name,
1324 Variable::Mode mode,
1325 FunctionLiteral* fun,
1326 bool resolve,
1327 bool* ok) {
1328 Variable* var = NULL;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001329 // If we are inside a function, a declaration of a var/const variable is a
1330 // truly local variable, and the scope of the variable is always the function
1331 // scope.
Steve Blocka7e24c12009-10-30 11:49:00 +00001332
1333 // If a function scope exists, then we can statically declare this
1334 // variable and also set its mode. In any case, a Declaration node
1335 // will be added to the scope so that the declaration can be added
1336 // to the corresponding activation frame at runtime if necessary.
1337 // For instance declarations inside an eval scope need to be added
1338 // to the calling function context.
Ben Murdoch257744e2011-11-30 15:57:28 +00001339 // Similarly, strict mode eval scope does not leak variable declarations to
1340 // the caller's scope so we declare all locals, too.
Ben Murdoch85b71792012-04-11 18:30:58 +01001341
1342 Scope* declaration_scope = mode == Variable::LET ? top_scope_
1343 : top_scope_->DeclarationScope();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001344 if (declaration_scope->is_function_scope() ||
Ben Murdoch85b71792012-04-11 18:30:58 +01001345 declaration_scope->is_strict_mode_eval_scope() ||
1346 declaration_scope->is_block_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 // Declare the variable in the function scope.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001348 var = declaration_scope->LocalLookup(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 if (var == NULL) {
1350 // Declare the name.
Ben Murdoch85b71792012-04-11 18:30:58 +01001351 var = declaration_scope->DeclareLocal(name, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 } else {
Ben Murdoch589d6972011-11-30 16:04:58 +00001353 // The name was declared in this scope before; check for conflicting
1354 // re-declarations. We have a conflict if either of the declarations is
1355 // not a var. There is similar code in runtime.cc in the Declare
1356 // functions. The function CheckNonConflictingScope checks for conflicting
1357 // var and let bindings from different scopes whereas this is a check for
1358 // conflicting declarations within the same scope. This check also covers
1359 //
1360 // function () { let x; { var x; } }
1361 //
1362 // because the var declaration is hoisted to the function scope where 'x'
1363 // is already bound.
Ben Murdoch85b71792012-04-11 18:30:58 +01001364 if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001365 // We only have vars, consts and lets in declarations.
Ben Murdoch85b71792012-04-11 18:30:58 +01001366 ASSERT(var->mode() == Variable::VAR ||
1367 var->mode() == Variable::CONST ||
1368 var->mode() == Variable::LET);
1369 if (harmony_block_scoping_) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001370 // In harmony mode we treat re-declarations as early errors. See
1371 // ES5 16 for a definition of early errors.
1372 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1373 const char* elms[2] = { "Variable", *c_string };
1374 Vector<const char*> args(elms, 2);
1375 ReportMessage("redeclaration", args);
1376 *ok = false;
Ben Murdoch85b71792012-04-11 18:30:58 +01001377 return NULL;
Ben Murdoch589d6972011-11-30 16:04:58 +00001378 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001379 const char* type = (var->mode() == Variable::VAR) ? "var" :
1380 (var->mode() == Variable::CONST) ? "const" : "let";
Steve Blocka7e24c12009-10-30 11:49:00 +00001381 Handle<String> type_string =
Steve Block44f0eee2011-05-26 01:26:41 +01001382 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001383 Expression* expression =
Steve Block44f0eee2011-05-26 01:26:41 +01001384 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00001385 type_string, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001386 declaration_scope->SetIllegalRedeclaration(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00001387 }
1388 }
1389 }
1390
1391 // We add a declaration node for every declaration. The compiler
1392 // will only generate code if necessary. In particular, declarations
1393 // for inner local variables that do not represent functions won't
1394 // result in any generated code.
1395 //
1396 // Note that we always add an unresolved proxy even if it's not
1397 // used, simply because we don't know in this method (w/o extra
1398 // parameters) if the proxy is needed or not. The proxy will be
1399 // bound during variable resolution time unless it was pre-bound
1400 // below.
1401 //
1402 // WARNING: This will lead to multiple declaration nodes for the
1403 // same variable if it is declared several times. This is not a
1404 // semantic issue as long as we keep the source order, but it may be
1405 // a performance issue since it may lead to repeated
1406 // Runtime::DeclareContextSlot() calls.
Ben Murdoch85b71792012-04-11 18:30:58 +01001407 VariableProxy* proxy = declaration_scope->NewUnresolved(
1408 name, false, scanner().location().beg_pos);
1409 declaration_scope->AddDeclaration(
1410 new(zone()) Declaration(proxy, mode, fun, top_scope_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001411
Ben Murdoch85b71792012-04-11 18:30:58 +01001412 // For global const variables we bind the proxy to a variable.
1413 if (mode == Variable::CONST && declaration_scope->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 ASSERT(resolve); // should be set by all callers
1415 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001416 var = new(zone()) Variable(declaration_scope,
1417 name,
Ben Murdoch85b71792012-04-11 18:30:58 +01001418 Variable::CONST,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001419 true,
Ben Murdoch85b71792012-04-11 18:30:58 +01001420 kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001421 }
1422
1423 // If requested and we have a local variable, bind the proxy to the variable
1424 // at parse-time. This is used for functions (and consts) declared inside
1425 // statements: the corresponding function (or const) variable must be in the
1426 // function scope and not a statement-local scope, e.g. as provided with a
1427 // 'with' statement:
1428 //
1429 // with (obj) {
1430 // function f() {}
1431 // }
1432 //
1433 // which is translated into:
1434 //
1435 // with (obj) {
1436 // // in this case this is not: 'var f; f = function () {};'
1437 // var f = function () {};
1438 // }
1439 //
1440 // Note that if 'f' is accessed from inside the 'with' statement, it
1441 // will be allocated in the context (because we must be able to look
1442 // it up dynamically) but it will also be accessed statically, i.e.,
1443 // with a context slot index and a context chain length for this
1444 // initialization code. Thus, inside the 'with' statement, we need
1445 // both access to the static and the dynamic context chain; the
1446 // runtime needs to provide both.
Ben Murdoch85b71792012-04-11 18:30:58 +01001447 if (resolve && var != NULL) proxy->BindTo(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001448
Ben Murdoch85b71792012-04-11 18:30:58 +01001449 return proxy;
Steve Blocka7e24c12009-10-30 11:49:00 +00001450}
1451
1452
1453// Language extension which is only enabled for source files loaded
1454// through the API's extension mechanism. A native function
1455// declaration is resolved by looking up the function through a
1456// callback provided by the extension.
1457Statement* Parser::ParseNativeDeclaration(bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001458 Expect(Token::FUNCTION, CHECK_OK);
1459 Handle<String> name = ParseIdentifier(CHECK_OK);
1460 Expect(Token::LPAREN, CHECK_OK);
1461 bool done = (peek() == Token::RPAREN);
1462 while (!done) {
1463 ParseIdentifier(CHECK_OK);
1464 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001465 if (!done) {
1466 Expect(Token::COMMA, CHECK_OK);
1467 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001468 }
1469 Expect(Token::RPAREN, CHECK_OK);
1470 Expect(Token::SEMICOLON, CHECK_OK);
1471
Steve Blocka7e24c12009-10-30 11:49:00 +00001472 // Make sure that the function containing the native declaration
1473 // isn't lazily compiled. The extension structures are only
1474 // accessible while parsing the first time not when reparsing
1475 // because of lazy compilation.
Ben Murdoch85b71792012-04-11 18:30:58 +01001476 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001477
1478 // Compute the function template for the native function.
1479 v8::Handle<v8::FunctionTemplate> fun_template =
1480 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1481 ASSERT(!fun_template.IsEmpty());
1482
Steve Block6ded16b2010-05-10 14:33:55 +01001483 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001484 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1485 const int literals = fun->NumberOfLiterals();
1486 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001487 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001488 Handle<SharedFunctionInfo> shared =
Steve Block44f0eee2011-05-26 01:26:41 +01001489 isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
Ben Murdoch85b71792012-04-11 18:30:58 +01001490 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001491 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001492
Steve Block6ded16b2010-05-10 14:33:55 +01001493 // Copy the function data to the shared function info.
1494 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001495 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001496 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001497
1498 // TODO(1240846): It's weird that native function declarations are
1499 // introduced dynamically when we meet their declarations, whereas
Ben Murdoch85b71792012-04-11 18:30:58 +01001500 // other functions are setup when entering the surrounding scope.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001501 SharedFunctionInfoLiteral* lit =
Ben Murdoch85b71792012-04-11 18:30:58 +01001502 new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
1503 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
1504 return new(zone()) ExpressionStatement(new(zone()) Assignment(
1505 isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001506}
1507
1508
Ben Murdoch85b71792012-04-11 18:30:58 +01001509Statement* Parser::ParseFunctionDeclaration(bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001510 // FunctionDeclaration ::
1511 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1512 Expect(Token::FUNCTION, CHECK_OK);
1513 int function_token_position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001514 bool is_strict_reserved = false;
1515 Handle<String> name = ParseIdentifierOrStrictReservedWord(
1516 &is_strict_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001517 FunctionLiteral* fun = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001518 is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001519 function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001520 FunctionLiteral::DECLARATION,
Steve Blocka7e24c12009-10-30 11:49:00 +00001521 CHECK_OK);
1522 // Even if we're not at the top-level of the global or a function
1523 // scope, we treat is as such and introduce the function with it's
1524 // initial value upon entering the corresponding scope.
Ben Murdoch85b71792012-04-11 18:30:58 +01001525 Variable::Mode mode = harmony_block_scoping_ ? Variable::LET : Variable::VAR;
1526 Declare(name, mode, fun, true, CHECK_OK);
1527 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001528}
1529
1530
1531Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001532 if (harmony_block_scoping_) return ParseScopedBlock(labels, ok);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001533
Steve Blocka7e24c12009-10-30 11:49:00 +00001534 // Block ::
1535 // '{' Statement* '}'
1536
1537 // Note that a Block does not introduce a new execution scope!
1538 // (ECMA-262, 3rd, 12.2)
1539 //
1540 // Construct block expecting 16 statements.
Ben Murdoch85b71792012-04-11 18:30:58 +01001541 Block* result = new(zone()) Block(isolate(), labels, 16, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001542 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001543 Expect(Token::LBRACE, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001544 InitializationBlockFinder block_finder(top_scope_, target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001545 while (peek() != Token::RBRACE) {
1546 Statement* stat = ParseStatement(NULL, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001547 if (stat && !stat->IsEmpty()) {
1548 result->AddStatement(stat);
1549 block_finder.Update(stat);
1550 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001551 }
1552 Expect(Token::RBRACE, CHECK_OK);
1553 return result;
1554}
1555
1556
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001557Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
1558 // Construct block expecting 16 statements.
Ben Murdoch85b71792012-04-11 18:30:58 +01001559 Block* body = new(zone()) Block(isolate(), labels, 16, false);
1560 Scope* saved_scope = top_scope_;
1561 Scope* block_scope = NewScope(top_scope_,
1562 Scope::BLOCK_SCOPE,
1563 inside_with());
1564 if (top_scope_->is_strict_mode()) {
1565 block_scope->EnableStrictMode();
1566 }
1567 top_scope_ = block_scope;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001568
1569 // Parse the statements and collect escaping labels.
Ben Murdoch85b71792012-04-11 18:30:58 +01001570 TargetCollector collector;
1571 Target target(&this->target_stack_, &collector);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001572 Expect(Token::LBRACE, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01001573 {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001574 Target target_body(&this->target_stack_, body);
1575 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1576
1577 while (peek() != Token::RBRACE) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001578 Statement* stat = ParseSourceElement(NULL, CHECK_OK);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001579 if (stat && !stat->IsEmpty()) {
1580 body->AddStatement(stat);
1581 block_finder.Update(stat);
1582 }
1583 }
1584 }
1585 Expect(Token::RBRACE, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01001586 top_scope_ = saved_scope;
1587
Ben Murdoch589d6972011-11-30 16:04:58 +00001588 block_scope = block_scope->FinalizeBlockScope();
1589 body->set_block_scope(block_scope);
1590 return body;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001591}
1592
1593
1594Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
1595 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001596 // VariableStatement ::
1597 // VariableDeclarations ';'
1598
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001599 Handle<String> ignore;
Ben Murdoch85b71792012-04-11 18:30:58 +01001600 Block* result = ParseVariableDeclarations(var_context,
1601 &ignore,
1602 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001603 ExpectSemicolon(CHECK_OK);
1604 return result;
1605}
1606
Steve Block44f0eee2011-05-26 01:26:41 +01001607
1608bool Parser::IsEvalOrArguments(Handle<String> string) {
1609 return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
1610 string.is_identical_to(isolate()->factory()->arguments_symbol());
Steve Block1e0659c2011-05-24 12:43:12 +01001611}
Steve Blocka7e24c12009-10-30 11:49:00 +00001612
Steve Block44f0eee2011-05-26 01:26:41 +01001613
Steve Blocka7e24c12009-10-30 11:49:00 +00001614// If the variable declaration declares exactly one non-const
Ben Murdoch85b71792012-04-11 18:30:58 +01001615// variable, then *var is set to that variable. In all other cases,
1616// *var is untouched; in particular, it is the caller's responsibility
Steve Blocka7e24c12009-10-30 11:49:00 +00001617// to initialize it properly. This mechanism is used for the parsing
1618// of 'for-in' loops.
Ben Murdoch85b71792012-04-11 18:30:58 +01001619Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
1620 Handle<String>* out,
1621 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001622 // VariableDeclarations ::
Ben Murdoch85b71792012-04-11 18:30:58 +01001623 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1624
1625 Variable::Mode mode = Variable::VAR;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001626 // True if the binding needs initialization. 'let' and 'const' declared
1627 // bindings are created uninitialized by their declaration nodes and
1628 // need initialization. 'var' declared bindings are always initialized
1629 // immediately by their declaration nodes.
1630 bool needs_init = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001631 bool is_const = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001632 Token::Value init_op = Token::INIT_VAR;
Steve Blocka7e24c12009-10-30 11:49:00 +00001633 if (peek() == Token::VAR) {
1634 Consume(Token::VAR);
1635 } else if (peek() == Token::CONST) {
1636 Consume(Token::CONST);
Ben Murdoch85b71792012-04-11 18:30:58 +01001637 if (top_scope_->is_strict_mode()) {
1638 ReportMessage("strict_const", Vector<const char*>::empty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001639 *ok = false;
1640 return NULL;
1641 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001642 mode = Variable::CONST;
1643 is_const = true;
1644 needs_init = true;
1645 init_op = Token::INIT_CONST;
1646 } else if (peek() == Token::LET) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001647 Consume(Token::LET);
Ben Murdoch85b71792012-04-11 18:30:58 +01001648 if (var_context != kSourceElement &&
1649 var_context != kForStatement) {
1650 ASSERT(var_context == kStatement);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001651 ReportMessage("unprotected_let", Vector<const char*>::empty());
1652 *ok = false;
1653 return NULL;
1654 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001655 mode = Variable::LET;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001656 needs_init = true;
1657 init_op = Token::INIT_LET;
Steve Blocka7e24c12009-10-30 11:49:00 +00001658 } else {
1659 UNREACHABLE(); // by current callers
1660 }
1661
Ben Murdoch85b71792012-04-11 18:30:58 +01001662 Scope* declaration_scope = mode == Variable::LET
1663 ? top_scope_ : top_scope_->DeclarationScope();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001664 // The scope of a var/const declared variable anywhere inside a function
Steve Blocka7e24c12009-10-30 11:49:00 +00001665 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001666 // transform a source-level var/const declaration into a (Function)
Steve Blocka7e24c12009-10-30 11:49:00 +00001667 // Scope declaration, and rewrite the source-level initialization into an
1668 // assignment statement. We use a block to collect multiple assignments.
1669 //
1670 // We mark the block as initializer block because we don't want the
1671 // rewriter to add a '.result' assignment to such a block (to get compliant
1672 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1673 // reasons when pretty-printing. Also, unless an assignment (initialization)
1674 // is inside an initializer block, it is ignored.
1675 //
1676 // Create new block with one expected declaration.
Ben Murdoch85b71792012-04-11 18:30:58 +01001677 Block* block = new(zone()) Block(isolate(), NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001678 int nvars = 0; // the number of variables declared
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001679 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001680 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001681 if (fni_ != NULL) fni_->Enter();
1682
Steve Blocka7e24c12009-10-30 11:49:00 +00001683 // Parse variable name.
1684 if (nvars > 0) Consume(Token::COMMA);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001685 name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001686 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001687
Steve Block1e0659c2011-05-24 12:43:12 +01001688 // Strict mode variables may not be named eval or arguments
Ben Murdoch85b71792012-04-11 18:30:58 +01001689 if (declaration_scope->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01001690 ReportMessage("strict_var_name", Vector<const char*>::empty());
1691 *ok = false;
1692 return NULL;
1693 }
1694
Steve Blocka7e24c12009-10-30 11:49:00 +00001695 // Declare variable.
1696 // Note that we *always* must treat the initial value via a separate init
1697 // assignment for variables and constants because the value must be assigned
1698 // when the variable is encountered in the source. But the variable/constant
1699 // is declared (and set to 'undefined') upon entering the function within
1700 // which the variable or constant is declared. Only function variables have
1701 // an initial value in the declaration (because they are initialized upon
1702 // entering the function).
1703 //
1704 // If we have a const declaration, in an inner scope, the proxy is always
1705 // bound to the declared variable (independent of possibly surrounding with
1706 // statements).
Ben Murdoch85b71792012-04-11 18:30:58 +01001707 Declare(name, mode, NULL, is_const /* always bound for CONST! */,
1708 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001709 nvars++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001710 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
Steve Block053d10c2011-06-13 19:13:29 +01001711 ReportMessageAt(scanner().location(), "too_many_variables",
1712 Vector<const char*>::empty());
1713 *ok = false;
1714 return NULL;
1715 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001716
1717 // Parse initialization expression if present and/or needed. A
1718 // declaration of the form:
1719 //
1720 // var v = x;
1721 //
1722 // is syntactic sugar for:
1723 //
1724 // var v; v = x;
1725 //
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001726 // In particular, we need to re-lookup 'v' (in top_scope_, not
1727 // declaration_scope) as it may be a different 'v' than the 'v' in the
1728 // declaration (e.g., if we are inside a 'with' statement or 'catch'
1729 // block).
Steve Blocka7e24c12009-10-30 11:49:00 +00001730 //
1731 // However, note that const declarations are different! A const
1732 // declaration of the form:
1733 //
1734 // const c = x;
1735 //
1736 // is *not* syntactic sugar for:
1737 //
1738 // const c; c = x;
1739 //
1740 // The "variable" c initialized to x is the same as the declared
1741 // one - there is no re-lookup (see the last parameter of the
1742 // Declare() call above).
1743
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001744 Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001745 Expression* value = NULL;
1746 int position = -1;
Ben Murdoch85b71792012-04-11 18:30:58 +01001747 if (peek() == Token::ASSIGN) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001748 Expect(Token::ASSIGN, CHECK_OK);
1749 position = scanner().location().beg_pos;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001750 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001751 // Don't infer if it is "a = function(){...}();"-like expression.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001752 if (fni_ != NULL &&
1753 value->AsCall() == NULL &&
1754 value->AsCallNew() == NULL) {
1755 fni_->Infer();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001756 } else {
1757 fni_->RemoveLastFunction();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001758 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001759 }
1760
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001761 // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
1762 if (value == NULL && needs_init) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001763 value = GetLiteralUndefined();
1764 }
1765
1766 // Global variable declarations must be compiled in a specific
1767 // way. When the script containing the global variable declaration
1768 // is entered, the global variable must be declared, so that if it
1769 // doesn't exist (not even in a prototype of the global object) it
1770 // gets created with an initial undefined value. This is handled
1771 // by the declarations part of the function representing the
1772 // top-level global code; see Runtime::DeclareGlobalVariable. If
1773 // it already exists (in the object or in a prototype), it is
1774 // *not* touched until the variable declaration statement is
1775 // executed.
1776 //
1777 // Executing the variable declaration statement will always
1778 // guarantee to give the global object a "local" variable; a
1779 // variable defined in the global object and not in any
1780 // prototype. This way, global variable declarations can shadow
1781 // properties in the prototype chain, but only after the variable
1782 // declaration statement has been executed. This is important in
1783 // browsers where the global object (window) has lots of
1784 // properties defined in prototype objects.
Ben Murdoch85b71792012-04-11 18:30:58 +01001785
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001786 if (initialization_scope->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001787 // Compute the arguments for the runtime call.
Ben Murdoch257744e2011-11-30 15:57:28 +00001788 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001789 // We have at least 1 parameter.
Ben Murdoch85b71792012-04-11 18:30:58 +01001790 arguments->Add(NewLiteral(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001791 CallRuntime* initialize;
1792
1793 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001794 arguments->Add(value);
1795 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001796
1797 // Construct the call to Runtime_InitializeConstGlobal
1798 // and add it to the initialization statement block.
1799 // Note that the function does different things depending on
1800 // the number of arguments (1 or 2).
Ben Murdoch85b71792012-04-11 18:30:58 +01001801 initialize =
1802 new(zone()) CallRuntime(
1803 isolate(),
1804 isolate()->factory()->InitializeConstGlobal_symbol(),
1805 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1806 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001807 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001808 // Add strict mode.
1809 // We may want to pass singleton to avoid Literal allocations.
Ben Murdoch85b71792012-04-11 18:30:58 +01001810 StrictModeFlag flag = initialization_scope->is_strict_mode()
1811 ? kStrictMode
1812 : kNonStrictMode;
1813 arguments->Add(NewNumberLiteral(flag));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001814
1815 // Be careful not to assign a value to the global variable if
1816 // we're in a with. The initialization value should not
1817 // necessarily be stored in the global object in that case,
1818 // which is why we need to generate a separate assignment node.
1819 if (value != NULL && !inside_with()) {
1820 arguments->Add(value);
1821 value = NULL; // zap the value to avoid the unnecessary assignment
1822 }
1823
1824 // Construct the call to Runtime_InitializeVarGlobal
1825 // and add it to the initialization statement block.
1826 // Note that the function does different things depending on
1827 // the number of arguments (2 or 3).
Ben Murdoch85b71792012-04-11 18:30:58 +01001828 initialize =
1829 new(zone()) CallRuntime(
1830 isolate(),
1831 isolate()->factory()->InitializeVarGlobal_symbol(),
1832 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1833 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001834 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001835
Ben Murdoch85b71792012-04-11 18:30:58 +01001836 block->AddStatement(new(zone()) ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001837 }
1838
Ben Murdoch589d6972011-11-30 16:04:58 +00001839 // Add an assignment node to the initialization statement block if we still
Ben Murdoch85b71792012-04-11 18:30:58 +01001840 // have a pending initialization value. We must distinguish between
1841 // different kinds of declarations: 'var' initializations are simply
1842 // assignments (with all the consequences if they are inside a 'with'
1843 // statement - they may change a 'with' object property). Constant
1844 // initializations always assign to the declared constant which is
1845 // always at the function scope level. This is only relevant for
1846 // dynamically looked-up variables and constants (the start context
1847 // for constant lookups is always the function context, while it is
1848 // the top context for var declared variables). Sigh...
1849 // For 'let' declared variables the initialization is in the same scope
1850 // as the declaration. Thus dynamic lookups are unnecessary even if the
1851 // block scope is inside a with.
Steve Blocka7e24c12009-10-30 11:49:00 +00001852 if (value != NULL) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001853 bool in_with = mode == Variable::VAR ? inside_with() : false;
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001854 VariableProxy* proxy =
Ben Murdoch85b71792012-04-11 18:30:58 +01001855 initialization_scope->NewUnresolved(name, in_with);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001856 Assignment* assignment =
Ben Murdoch85b71792012-04-11 18:30:58 +01001857 new(zone()) Assignment(isolate(), init_op, proxy, value, position);
1858 if (block) {
1859 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1860 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001861 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001862
1863 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001864 } while (peek() == Token::COMMA);
1865
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001866 // If there was a single non-const declaration, return it in the output
1867 // parameter for possible use by for/in.
1868 if (nvars == 1 && !is_const) {
1869 *out = name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001870 }
1871
1872 return block;
1873}
1874
1875
1876static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1877 ASSERT(!label.is_null());
1878 if (labels != NULL)
1879 for (int i = labels->length(); i-- > 0; )
1880 if (labels->at(i).is_identical_to(label))
1881 return true;
1882
1883 return false;
1884}
1885
1886
1887Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1888 bool* ok) {
1889 // ExpressionStatement | LabelledStatement ::
1890 // Expression ';'
1891 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001892 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001893 Expression* expr = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001894 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001895 expr->AsVariableProxy() != NULL &&
1896 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001897 // Expression is a single identifier, and not, e.g., a parenthesized
1898 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001899 VariableProxy* var = expr->AsVariableProxy();
1900 Handle<String> label = var->name();
1901 // TODO(1240780): We don't check for redeclaration of labels
1902 // during preparsing since keeping track of the set of active
1903 // labels requires nontrivial changes to the way scopes are
1904 // structured. However, these are probably changes we want to
1905 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001906 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001907 SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001908 const char* elms[2] = { "Label", *c_string };
1909 Vector<const char*> args(elms, 2);
1910 ReportMessage("redeclaration", args);
1911 *ok = false;
1912 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001913 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001914 if (labels == NULL) labels = new(zone()) ZoneStringList(4);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001915 labels->Add(label);
1916 // Remove the "ghost" variable that turned out to be a label
1917 // from the top scope. This way, we don't try to resolve it
1918 // during the scope processing.
1919 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001920 Expect(Token::COLON, CHECK_OK);
1921 return ParseStatement(labels, ok);
1922 }
1923
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001924 // If we have an extension, we allow a native function declaration.
1925 // A native function declaration starts with "native function" with
1926 // no line-terminator between the two words.
1927 if (extension_ != NULL &&
1928 peek() == Token::FUNCTION &&
1929 !scanner().HasAnyLineTerminatorBeforeNext() &&
1930 expr != NULL &&
1931 expr->AsVariableProxy() != NULL &&
1932 expr->AsVariableProxy()->name()->Equals(
1933 isolate()->heap()->native_symbol()) &&
1934 !scanner().literal_contains_escapes()) {
1935 return ParseNativeDeclaration(ok);
1936 }
1937
Ben Murdoch85b71792012-04-11 18:30:58 +01001938 // Parsed expression statement.
1939 ExpectSemicolon(CHECK_OK);
1940 return new(zone()) ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001941}
1942
1943
1944IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1945 // IfStatement ::
1946 // 'if' '(' Expression ')' Statement ('else' Statement)?
1947
1948 Expect(Token::IF, CHECK_OK);
1949 Expect(Token::LPAREN, CHECK_OK);
1950 Expression* condition = ParseExpression(true, CHECK_OK);
1951 Expect(Token::RPAREN, CHECK_OK);
1952 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1953 Statement* else_statement = NULL;
1954 if (peek() == Token::ELSE) {
1955 Next();
1956 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001957 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +01001958 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001959 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001960 return new(zone()) IfStatement(
1961 isolate(), condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001962}
1963
1964
1965Statement* Parser::ParseContinueStatement(bool* ok) {
1966 // ContinueStatement ::
1967 // 'continue' Identifier? ';'
1968
1969 Expect(Token::CONTINUE, CHECK_OK);
1970 Handle<String> label = Handle<String>::null();
1971 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001972 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001973 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1974 label = ParseIdentifier(CHECK_OK);
1975 }
1976 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001977 target = LookupContinueTarget(label, CHECK_OK);
1978 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001979 // Illegal continue statement.
1980 const char* message = "illegal_continue";
1981 Vector<Handle<String> > args;
1982 if (!label.is_null()) {
1983 message = "unknown_label";
1984 args = Vector<Handle<String> >(&label, 1);
1985 }
1986 ReportMessageAt(scanner().location(), message, args);
1987 *ok = false;
1988 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001989 }
1990 ExpectSemicolon(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01001991 return new(zone()) ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001992}
1993
1994
1995Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1996 // BreakStatement ::
1997 // 'break' Identifier? ';'
1998
1999 Expect(Token::BREAK, CHECK_OK);
2000 Handle<String> label;
2001 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002002 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00002003 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2004 label = ParseIdentifier(CHECK_OK);
2005 }
2006 // Parse labeled break statements that target themselves into
2007 // empty statements, e.g. 'l1: l2: l3: break l2;'
2008 if (!label.is_null() && ContainsLabel(labels, label)) {
Ben Murdoch85b71792012-04-11 18:30:58 +01002009 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002010 }
2011 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002012 target = LookupBreakTarget(label, CHECK_OK);
2013 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002014 // Illegal break statement.
2015 const char* message = "illegal_break";
2016 Vector<Handle<String> > args;
2017 if (!label.is_null()) {
2018 message = "unknown_label";
2019 args = Vector<Handle<String> >(&label, 1);
2020 }
2021 ReportMessageAt(scanner().location(), message, args);
2022 *ok = false;
2023 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002024 }
2025 ExpectSemicolon(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002026 return new(zone()) BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00002027}
2028
2029
2030Statement* Parser::ParseReturnStatement(bool* ok) {
2031 // ReturnStatement ::
2032 // 'return' Expression? ';'
2033
2034 // Consume the return token. It is necessary to do the before
2035 // reporting any errors on it, because of the way errors are
2036 // reported (underlining).
2037 Expect(Token::RETURN, CHECK_OK);
2038
Ben Murdoch692be652012-01-10 18:47:50 +00002039 Token::Value tok = peek();
2040 Statement* result;
2041 if (scanner().HasAnyLineTerminatorBeforeNext() ||
2042 tok == Token::SEMICOLON ||
2043 tok == Token::RBRACE ||
2044 tok == Token::EOS) {
2045 ExpectSemicolon(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002046 result = new(zone()) ReturnStatement(GetLiteralUndefined());
Ben Murdoch692be652012-01-10 18:47:50 +00002047 } else {
2048 Expression* expr = ParseExpression(true, CHECK_OK);
2049 ExpectSemicolon(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002050 result = new(zone()) ReturnStatement(expr);
Ben Murdoch692be652012-01-10 18:47:50 +00002051 }
2052
Steve Blocka7e24c12009-10-30 11:49:00 +00002053 // An ECMAScript program is considered syntactically incorrect if it
2054 // contains a return statement that is not within the body of a
2055 // function. See ECMA-262, section 12.9, page 67.
2056 //
2057 // To be consistent with KJS we report the syntax error at runtime.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002058 Scope* declaration_scope = top_scope_->DeclarationScope();
2059 if (declaration_scope->is_global_scope() ||
2060 declaration_scope->is_eval_scope()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002061 Handle<String> type = isolate()->factory()->illegal_return_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002062 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Ben Murdoch85b71792012-04-11 18:30:58 +01002063 return new(zone()) ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00002064 }
Ben Murdoch692be652012-01-10 18:47:50 +00002065 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002066}
2067
2068
Steve Blocka7e24c12009-10-30 11:49:00 +00002069Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
2070 // WithStatement ::
2071 // 'with' '(' Expression ')' Statement
2072
2073 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002074
Ben Murdoch85b71792012-04-11 18:30:58 +01002075 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002076 ReportMessage("strict_mode_with", Vector<const char*>::empty());
2077 *ok = false;
2078 return NULL;
2079 }
2080
Steve Blocka7e24c12009-10-30 11:49:00 +00002081 Expect(Token::LPAREN, CHECK_OK);
2082 Expression* expr = ParseExpression(true, CHECK_OK);
2083 Expect(Token::RPAREN, CHECK_OK);
2084
Ben Murdoch85b71792012-04-11 18:30:58 +01002085 ++with_nesting_level_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002086 top_scope_->DeclarationScope()->RecordWithStatement();
Ben Murdoch85b71792012-04-11 18:30:58 +01002087 Statement* stmt = ParseStatement(labels, CHECK_OK);
2088 --with_nesting_level_;
2089 return new(zone()) WithStatement(expr, stmt);
Steve Blocka7e24c12009-10-30 11:49:00 +00002090}
2091
2092
2093CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2094 // CaseClause ::
2095 // 'case' Expression ':' Statement*
2096 // 'default' ':' Statement*
2097
2098 Expression* label = NULL; // NULL expression indicates default case
2099 if (peek() == Token::CASE) {
2100 Expect(Token::CASE, CHECK_OK);
2101 label = ParseExpression(true, CHECK_OK);
2102 } else {
2103 Expect(Token::DEFAULT, CHECK_OK);
2104 if (*default_seen_ptr) {
2105 ReportMessage("multiple_defaults_in_switch",
2106 Vector<const char*>::empty());
2107 *ok = false;
2108 return NULL;
2109 }
2110 *default_seen_ptr = true;
2111 }
2112 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002113 int pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00002114 ZoneList<Statement*>* statements = new(zone()) ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00002115 while (peek() != Token::CASE &&
2116 peek() != Token::DEFAULT &&
2117 peek() != Token::RBRACE) {
2118 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002119 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00002120 }
2121
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002122 return new(zone()) CaseClause(isolate(), label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002123}
2124
2125
2126SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2127 bool* ok) {
2128 // SwitchStatement ::
2129 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2130
Ben Murdoch85b71792012-04-11 18:30:58 +01002131 SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002132 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002133
2134 Expect(Token::SWITCH, CHECK_OK);
2135 Expect(Token::LPAREN, CHECK_OK);
2136 Expression* tag = ParseExpression(true, CHECK_OK);
2137 Expect(Token::RPAREN, CHECK_OK);
2138
2139 bool default_seen = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00002140 ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002141 Expect(Token::LBRACE, CHECK_OK);
2142 while (peek() != Token::RBRACE) {
2143 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002144 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002145 }
2146 Expect(Token::RBRACE, CHECK_OK);
2147
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002148 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002149 return statement;
2150}
2151
2152
2153Statement* Parser::ParseThrowStatement(bool* ok) {
2154 // ThrowStatement ::
2155 // 'throw' Expression ';'
2156
2157 Expect(Token::THROW, CHECK_OK);
2158 int pos = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002159 if (scanner().HasAnyLineTerminatorBeforeNext()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002160 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2161 *ok = false;
2162 return NULL;
2163 }
2164 Expression* exception = ParseExpression(true, CHECK_OK);
2165 ExpectSemicolon(CHECK_OK);
2166
Ben Murdoch85b71792012-04-11 18:30:58 +01002167 return new(zone()) ExpressionStatement(
2168 new(zone()) Throw(isolate(), exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002169}
2170
2171
2172TryStatement* Parser::ParseTryStatement(bool* ok) {
2173 // TryStatement ::
2174 // 'try' Block Catch
2175 // 'try' Block Finally
2176 // 'try' Block Catch Finally
2177 //
2178 // Catch ::
2179 // 'catch' '(' Identifier ')' Block
2180 //
2181 // Finally ::
2182 // 'finally' Block
2183
2184 Expect(Token::TRY, CHECK_OK);
2185
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002186 TargetCollector try_collector;
Steve Blocka7e24c12009-10-30 11:49:00 +00002187 Block* try_block;
2188
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002189 { Target target(&this->target_stack_, &try_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002190 try_block = ParseBlock(NULL, CHECK_OK);
2191 }
2192
Steve Blocka7e24c12009-10-30 11:49:00 +00002193 Token::Value tok = peek();
2194 if (tok != Token::CATCH && tok != Token::FINALLY) {
2195 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2196 *ok = false;
2197 return NULL;
2198 }
2199
2200 // If we can break out from the catch block and there is a finally block,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002201 // then we will need to collect escaping targets from the catch
2202 // block. Since we don't know yet if there will be a finally block, we
2203 // always collect the targets.
2204 TargetCollector catch_collector;
2205 Scope* catch_scope = NULL;
2206 Variable* catch_variable = NULL;
2207 Block* catch_block = NULL;
2208 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002209 if (tok == Token::CATCH) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002210 Consume(Token::CATCH);
2211
2212 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002213 name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002214
Ben Murdoch85b71792012-04-11 18:30:58 +01002215 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01002216 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2217 *ok = false;
2218 return NULL;
2219 }
2220
Steve Blocka7e24c12009-10-30 11:49:00 +00002221 Expect(Token::RPAREN, CHECK_OK);
2222
2223 if (peek() == Token::LBRACE) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002224 Target target(&this->target_stack_, &catch_collector);
Ben Murdoch85b71792012-04-11 18:30:58 +01002225 catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with());
2226 if (top_scope_->is_strict_mode()) {
2227 catch_scope->EnableStrictMode();
2228 }
2229 Variable::Mode mode = harmony_block_scoping_
2230 ? Variable::LET : Variable::VAR;
2231 catch_variable = catch_scope->DeclareLocal(name, mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002232
Ben Murdoch85b71792012-04-11 18:30:58 +01002233 Scope* saved_scope = top_scope_;
2234 top_scope_ = catch_scope;
Ben Murdoch589d6972011-11-30 16:04:58 +00002235 catch_block = ParseBlock(NULL, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002236 top_scope_ = saved_scope;
Steve Blocka7e24c12009-10-30 11:49:00 +00002237 } else {
2238 Expect(Token::LBRACE, CHECK_OK);
2239 }
Ben Murdoch85b71792012-04-11 18:30:58 +01002240
Steve Blocka7e24c12009-10-30 11:49:00 +00002241 tok = peek();
2242 }
2243
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002244 Block* finally_block = NULL;
2245 if (tok == Token::FINALLY || catch_block == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002246 Consume(Token::FINALLY);
Steve Blocka7e24c12009-10-30 11:49:00 +00002247 finally_block = ParseBlock(NULL, CHECK_OK);
2248 }
2249
2250 // Simplify the AST nodes by converting:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002251 // 'try B0 catch B1 finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002252 // to:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002253 // 'try { try B0 catch B1 } finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002254
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002255 if (catch_block != NULL && finally_block != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002256 // If we have both, create an inner try/catch.
2257 ASSERT(catch_scope != NULL && catch_variable != NULL);
Ben Murdoch85b71792012-04-11 18:30:58 +01002258 TryCatchStatement* statement =
2259 new(zone()) TryCatchStatement(try_block,
2260 catch_scope,
2261 catch_variable,
2262 catch_block);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002263 statement->set_escaping_targets(try_collector.targets());
Ben Murdoch85b71792012-04-11 18:30:58 +01002264 try_block = new(zone()) Block(isolate(), NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002265 try_block->AddStatement(statement);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002266 catch_block = NULL; // Clear to indicate it's been handled.
Steve Blocka7e24c12009-10-30 11:49:00 +00002267 }
2268
2269 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002270 if (catch_block != NULL) {
2271 ASSERT(finally_block == NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002272 ASSERT(catch_scope != NULL && catch_variable != NULL);
Ben Murdoch85b71792012-04-11 18:30:58 +01002273 result =
2274 new(zone()) TryCatchStatement(try_block,
2275 catch_scope,
2276 catch_variable,
2277 catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002278 } else {
2279 ASSERT(finally_block != NULL);
Ben Murdoch85b71792012-04-11 18:30:58 +01002280 result = new(zone()) TryFinallyStatement(try_block, finally_block);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002281 // Combine the jump targets of the try block and the possible catch block.
2282 try_collector.targets()->AddAll(*catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002283 }
2284
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002285 result->set_escaping_targets(try_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002286 return result;
2287}
2288
2289
Steve Block3ce2e202009-11-05 08:53:23 +00002290DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2291 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002292 // DoStatement ::
2293 // 'do' Statement 'while' '(' Expression ')' ';'
2294
Ben Murdoch85b71792012-04-11 18:30:58 +01002295 DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002296 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002297
2298 Expect(Token::DO, CHECK_OK);
2299 Statement* body = ParseStatement(NULL, CHECK_OK);
2300 Expect(Token::WHILE, CHECK_OK);
2301 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002302
2303 if (loop != NULL) {
2304 int position = scanner().location().beg_pos;
2305 loop->set_condition_position(position);
2306 }
2307
Steve Blocka7e24c12009-10-30 11:49:00 +00002308 Expression* cond = ParseExpression(true, CHECK_OK);
2309 Expect(Token::RPAREN, CHECK_OK);
2310
2311 // Allow do-statements to be terminated with and without
2312 // semi-colons. This allows code such as 'do;while(0)return' to
2313 // parse, which would not be the case if we had used the
2314 // ExpectSemicolon() functionality here.
2315 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2316
Steve Block3ce2e202009-11-05 08:53:23 +00002317 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002318 return loop;
2319}
2320
2321
Steve Block3ce2e202009-11-05 08:53:23 +00002322WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002323 // WhileStatement ::
2324 // 'while' '(' Expression ')' Statement
2325
Ben Murdoch85b71792012-04-11 18:30:58 +01002326 WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002327 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002328
2329 Expect(Token::WHILE, CHECK_OK);
2330 Expect(Token::LPAREN, CHECK_OK);
2331 Expression* cond = ParseExpression(true, CHECK_OK);
2332 Expect(Token::RPAREN, CHECK_OK);
2333 Statement* body = ParseStatement(NULL, CHECK_OK);
2334
Steve Block3ce2e202009-11-05 08:53:23 +00002335 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002336 return loop;
2337}
2338
2339
2340Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2341 // ForStatement ::
2342 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2343
2344 Statement* init = NULL;
2345
2346 Expect(Token::FOR, CHECK_OK);
2347 Expect(Token::LPAREN, CHECK_OK);
2348 if (peek() != Token::SEMICOLON) {
2349 if (peek() == Token::VAR || peek() == Token::CONST) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002350 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002351 Block* variable_statement =
Ben Murdoch85b71792012-04-11 18:30:58 +01002352 ParseVariableDeclarations(kForStatement, &name, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002353
2354 if (peek() == Token::IN && !name.is_null()) {
Ben Murdoch85b71792012-04-11 18:30:58 +01002355 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with());
2356 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002357 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002358
2359 Expect(Token::IN, CHECK_OK);
2360 Expression* enumerable = ParseExpression(true, CHECK_OK);
2361 Expect(Token::RPAREN, CHECK_OK);
2362
2363 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002364 loop->Initialize(each, enumerable, body);
Ben Murdoch85b71792012-04-11 18:30:58 +01002365 Block* result = new(zone()) Block(isolate(), NULL, 2, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002366 result->AddStatement(variable_statement);
2367 result->AddStatement(loop);
2368 // Parsed for-in loop w/ variable/const declaration.
2369 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002370 } else {
2371 init = variable_statement;
2372 }
2373
2374 } else {
2375 Expression* expression = ParseExpression(false, CHECK_OK);
2376 if (peek() == Token::IN) {
2377 // Signal a reference error if the expression is an invalid
2378 // left-hand side expression. We could report this as a syntax
2379 // error here but for compatibility with JSC we choose to report
2380 // the error at runtime.
2381 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002382 Handle<String> type =
2383 isolate()->factory()->invalid_lhs_in_for_in_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002384 expression = NewThrowReferenceError(type);
2385 }
Ben Murdoch85b71792012-04-11 18:30:58 +01002386 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002387 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002388
2389 Expect(Token::IN, CHECK_OK);
2390 Expression* enumerable = ParseExpression(true, CHECK_OK);
2391 Expect(Token::RPAREN, CHECK_OK);
2392
2393 Statement* body = ParseStatement(NULL, CHECK_OK);
2394 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002395 // Parsed for-in loop.
2396 return loop;
2397
2398 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +01002399 init = new(zone()) ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002400 }
2401 }
2402 }
2403
2404 // Standard 'for' loop
Ben Murdoch85b71792012-04-11 18:30:58 +01002405 ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002406 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002407
2408 // Parsed initializer at this point.
2409 Expect(Token::SEMICOLON, CHECK_OK);
2410
2411 Expression* cond = NULL;
2412 if (peek() != Token::SEMICOLON) {
2413 cond = ParseExpression(true, CHECK_OK);
2414 }
2415 Expect(Token::SEMICOLON, CHECK_OK);
2416
2417 Statement* next = NULL;
2418 if (peek() != Token::RPAREN) {
2419 Expression* exp = ParseExpression(true, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002420 next = new(zone()) ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002421 }
2422 Expect(Token::RPAREN, CHECK_OK);
2423
2424 Statement* body = ParseStatement(NULL, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002425 if (loop) loop->Initialize(init, cond, next, body);
2426 return loop;
Steve Blocka7e24c12009-10-30 11:49:00 +00002427}
2428
2429
2430// Precedence = 1
2431Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2432 // Expression ::
2433 // AssignmentExpression
2434 // Expression ',' AssignmentExpression
2435
2436 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2437 while (peek() == Token::COMMA) {
2438 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002439 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002440 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002441 result = new(zone()) BinaryOperation(
2442 isolate(), Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002443 }
2444 return result;
2445}
2446
2447
2448// Precedence = 2
2449Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2450 // AssignmentExpression ::
2451 // ConditionalExpression
2452 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2453
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002454 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002455 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2456
2457 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002458 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002459 // Parsed conditional expression only (no assignment).
2460 return expression;
2461 }
2462
2463 // Signal a reference error if the expression is an invalid left-hand
2464 // side expression. We could report this as a syntax error here but
2465 // for compatibility with JSC we choose to report the error at
2466 // runtime.
2467 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002468 Handle<String> type =
2469 isolate()->factory()->invalid_lhs_in_assignment_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002470 expression = NewThrowReferenceError(type);
2471 }
2472
Ben Murdoch85b71792012-04-11 18:30:58 +01002473 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002474 // Assignment to eval or arguments is disallowed in strict mode.
2475 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2476 }
2477
Steve Blocka7e24c12009-10-30 11:49:00 +00002478 Token::Value op = Next(); // Get assignment operator.
2479 int pos = scanner().location().beg_pos;
2480 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2481
2482 // TODO(1231235): We try to estimate the set of properties set by
2483 // constructors. We define a new property whenever there is an
2484 // assignment to a property of 'this'. We should probably only add
2485 // properties if we haven't seen them before. Otherwise we'll
2486 // probably overestimate the number of properties.
2487 Property* property = expression ? expression->AsProperty() : NULL;
2488 if (op == Token::ASSIGN &&
2489 property != NULL &&
2490 property->obj()->AsVariableProxy() != NULL &&
2491 property->obj()->AsVariableProxy()->is_this()) {
Ben Murdoch85b71792012-04-11 18:30:58 +01002492 lexical_scope_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002493 }
2494
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002495 // If we assign a function literal to a property we pretenure the
2496 // literal so it can be added as a constant function property.
2497 if (property != NULL && right->AsFunctionLiteral() != NULL) {
Ben Murdoch85b71792012-04-11 18:30:58 +01002498 right->AsFunctionLiteral()->set_pretenure(true);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002499 }
2500
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002501 if (fni_ != NULL) {
2502 // Check if the right hand side is a call to avoid inferring a
2503 // name if we're dealing with "a = function(){...}();"-like
2504 // expression.
2505 if ((op == Token::INIT_VAR
2506 || op == Token::INIT_CONST
2507 || op == Token::ASSIGN)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002508 && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002509 fni_->Infer();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002510 } else {
2511 fni_->RemoveLastFunction();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002512 }
2513 fni_->Leave();
2514 }
2515
Ben Murdoch85b71792012-04-11 18:30:58 +01002516 return new(zone()) Assignment(isolate(), op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002517}
2518
2519
2520// Precedence = 3
2521Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2522 // ConditionalExpression ::
2523 // LogicalOrExpression
2524 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2525
2526 // We start using the binary expression parser for prec >= 4 only!
2527 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2528 if (peek() != Token::CONDITIONAL) return expression;
2529 Consume(Token::CONDITIONAL);
2530 // In parsing the first assignment expression in conditional
2531 // expressions we always accept the 'in' keyword; see ECMA-262,
2532 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002533 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002534 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2535 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002536 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002537 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002538 return new(zone()) Conditional(
2539 isolate(), expression, left, right, left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002540}
2541
2542
2543static int Precedence(Token::Value tok, bool accept_IN) {
2544 if (tok == Token::IN && !accept_IN)
2545 return 0; // 0 precedence will terminate binary expression parsing
2546
2547 return Token::Precedence(tok);
2548}
2549
2550
2551// Precedence >= 4
2552Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2553 ASSERT(prec >= 4);
2554 Expression* x = ParseUnaryExpression(CHECK_OK);
2555 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2556 // prec1 >= 4
2557 while (Precedence(peek(), accept_IN) == prec1) {
2558 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002559 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002560 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2561
2562 // Compute some expressions involving only number literals.
2563 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2564 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2565 double x_val = x->AsLiteral()->handle()->Number();
2566 double y_val = y->AsLiteral()->handle()->Number();
2567
2568 switch (op) {
2569 case Token::ADD:
Ben Murdoch85b71792012-04-11 18:30:58 +01002570 x = NewNumberLiteral(x_val + y_val);
Steve Blocka7e24c12009-10-30 11:49:00 +00002571 continue;
2572 case Token::SUB:
Ben Murdoch85b71792012-04-11 18:30:58 +01002573 x = NewNumberLiteral(x_val - y_val);
Steve Blocka7e24c12009-10-30 11:49:00 +00002574 continue;
2575 case Token::MUL:
Ben Murdoch85b71792012-04-11 18:30:58 +01002576 x = NewNumberLiteral(x_val * y_val);
Steve Blocka7e24c12009-10-30 11:49:00 +00002577 continue;
2578 case Token::DIV:
Ben Murdoch85b71792012-04-11 18:30:58 +01002579 x = NewNumberLiteral(x_val / y_val);
Steve Blocka7e24c12009-10-30 11:49:00 +00002580 continue;
Ben Murdoch85b71792012-04-11 18:30:58 +01002581 case Token::BIT_OR:
2582 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
Steve Blocka7e24c12009-10-30 11:49:00 +00002583 continue;
Ben Murdoch85b71792012-04-11 18:30:58 +01002584 case Token::BIT_AND:
2585 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
Steve Blocka7e24c12009-10-30 11:49:00 +00002586 continue;
Ben Murdoch85b71792012-04-11 18:30:58 +01002587 case Token::BIT_XOR:
2588 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
Steve Blocka7e24c12009-10-30 11:49:00 +00002589 continue;
2590 case Token::SHL: {
2591 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
Ben Murdoch85b71792012-04-11 18:30:58 +01002592 x = NewNumberLiteral(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002593 continue;
2594 }
2595 case Token::SHR: {
2596 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2597 uint32_t value = DoubleToUint32(x_val) >> shift;
Ben Murdoch85b71792012-04-11 18:30:58 +01002598 x = NewNumberLiteral(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002599 continue;
2600 }
2601 case Token::SAR: {
2602 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2603 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
Ben Murdoch85b71792012-04-11 18:30:58 +01002604 x = NewNumberLiteral(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002605 continue;
2606 }
2607 default:
2608 break;
2609 }
2610 }
2611
Steve Blocka7e24c12009-10-30 11:49:00 +00002612 // For now we distinguish between comparisons and other binary
2613 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002614 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002615 if (Token::IsCompareOp(op)) {
2616 // We have a comparison.
2617 Token::Value cmp = op;
2618 switch (op) {
2619 case Token::NE: cmp = Token::EQ; break;
2620 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2621 default: break;
2622 }
Ben Murdoch85b71792012-04-11 18:30:58 +01002623 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002624 if (cmp != op) {
2625 // The comparison was negated - add a NOT.
Ben Murdoch85b71792012-04-11 18:30:58 +01002626 x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002627 }
2628
2629 } else {
2630 // We have a "normal" binary operation.
Ben Murdoch85b71792012-04-11 18:30:58 +01002631 x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002632 }
2633 }
2634 }
2635 return x;
2636}
2637
2638
Ben Murdoch85b71792012-04-11 18:30:58 +01002639Expression* Parser::NewCompareNode(Token::Value op,
2640 Expression* x,
2641 Expression* y,
2642 int position) {
2643 ASSERT(op != Token::NE && op != Token::NE_STRICT);
2644 if (op == Token::EQ || op == Token::EQ_STRICT) {
2645 bool is_strict = (op == Token::EQ_STRICT);
2646 Literal* x_literal = x->AsLiteral();
2647 if (x_literal != NULL && x_literal->IsNull()) {
2648 return new(zone()) CompareToNull(isolate(), is_strict, y);
2649 }
2650
2651 Literal* y_literal = y->AsLiteral();
2652 if (y_literal != NULL && y_literal->IsNull()) {
2653 return new(zone()) CompareToNull(isolate(), is_strict, x);
2654 }
2655 }
2656 return new(zone()) CompareOperation(isolate(), op, x, y, position);
2657}
2658
2659
Steve Blocka7e24c12009-10-30 11:49:00 +00002660Expression* Parser::ParseUnaryExpression(bool* ok) {
2661 // UnaryExpression ::
2662 // PostfixExpression
2663 // 'delete' UnaryExpression
2664 // 'void' UnaryExpression
2665 // 'typeof' UnaryExpression
2666 // '++' UnaryExpression
2667 // '--' UnaryExpression
2668 // '+' UnaryExpression
2669 // '-' UnaryExpression
2670 // '~' UnaryExpression
2671 // '!' UnaryExpression
2672
2673 Token::Value op = peek();
2674 if (Token::IsUnaryOp(op)) {
2675 op = Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00002676 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002677 Expression* expression = ParseUnaryExpression(CHECK_OK);
2678
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002679 if (expression != NULL && (expression->AsLiteral() != NULL)) {
2680 Handle<Object> literal = expression->AsLiteral()->handle();
2681 if (op == Token::NOT) {
2682 // Convert the literal to a boolean condition and negate it.
2683 bool condition = literal->ToBoolean()->IsTrue();
2684 Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
Ben Murdoch85b71792012-04-11 18:30:58 +01002685 return NewLiteral(result);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002686 } else if (literal->IsNumber()) {
2687 // Compute some expressions involving only number literals.
2688 double value = literal->Number();
2689 switch (op) {
2690 case Token::ADD:
2691 return expression;
2692 case Token::SUB:
Ben Murdoch85b71792012-04-11 18:30:58 +01002693 return NewNumberLiteral(-value);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002694 case Token::BIT_NOT:
Ben Murdoch85b71792012-04-11 18:30:58 +01002695 return NewNumberLiteral(~DoubleToInt32(value));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002696 default:
2697 break;
2698 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002699 }
2700 }
2701
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002702 // "delete identifier" is a syntax error in strict mode.
Ben Murdoch85b71792012-04-11 18:30:58 +01002703 if (op == Token::DELETE && top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002704 VariableProxy* operand = expression->AsVariableProxy();
2705 if (operand != NULL && !operand->is_this()) {
2706 ReportMessage("strict_delete", Vector<const char*>::empty());
2707 *ok = false;
2708 return NULL;
2709 }
2710 }
2711
Ben Murdoch85b71792012-04-11 18:30:58 +01002712 return new(zone()) UnaryOperation(isolate(), op, expression, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002713
2714 } else if (Token::IsCountOp(op)) {
2715 op = Next();
2716 Expression* expression = ParseUnaryExpression(CHECK_OK);
2717 // Signal a reference error if the expression is an invalid
2718 // left-hand side expression. We could report this as a syntax
2719 // error here but for compatibility with JSC we choose to report the
2720 // error at runtime.
2721 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002722 Handle<String> type =
2723 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002724 expression = NewThrowReferenceError(type);
2725 }
Steve Block1e0659c2011-05-24 12:43:12 +01002726
Ben Murdoch85b71792012-04-11 18:30:58 +01002727 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002728 // Prefix expression operand in strict mode may not be eval or arguments.
2729 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2730 }
2731
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002732 int position = scanner().location().beg_pos;
Ben Murdoch85b71792012-04-11 18:30:58 +01002733 return new(zone()) CountOperation(isolate(),
2734 op,
2735 true /* prefix */,
2736 expression,
2737 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002738
2739 } else {
2740 return ParsePostfixExpression(ok);
2741 }
2742}
2743
2744
2745Expression* Parser::ParsePostfixExpression(bool* ok) {
2746 // PostfixExpression ::
2747 // LeftHandSideExpression ('++' | '--')?
2748
2749 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002750 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Ben Murdochb0fe1622011-05-05 13:52:32 +01002751 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002752 // Signal a reference error if the expression is an invalid
2753 // left-hand side expression. We could report this as a syntax
2754 // error here but for compatibility with JSC we choose to report the
2755 // error at runtime.
2756 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002757 Handle<String> type =
2758 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002759 expression = NewThrowReferenceError(type);
2760 }
Steve Block1e0659c2011-05-24 12:43:12 +01002761
Ben Murdoch85b71792012-04-11 18:30:58 +01002762 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002763 // Postfix expression operand in strict mode may not be eval or arguments.
2764 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2765 }
2766
Steve Blocka7e24c12009-10-30 11:49:00 +00002767 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002768 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002769 expression =
Ben Murdoch85b71792012-04-11 18:30:58 +01002770 new(zone()) CountOperation(isolate(),
2771 next,
2772 false /* postfix */,
2773 expression,
2774 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002775 }
2776 return expression;
2777}
2778
2779
2780Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2781 // LeftHandSideExpression ::
2782 // (NewExpression | MemberExpression) ...
2783
2784 Expression* result;
2785 if (peek() == Token::NEW) {
2786 result = ParseNewExpression(CHECK_OK);
2787 } else {
2788 result = ParseMemberExpression(CHECK_OK);
2789 }
2790
2791 while (true) {
2792 switch (peek()) {
2793 case Token::LBRACK: {
2794 Consume(Token::LBRACK);
2795 int pos = scanner().location().beg_pos;
2796 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002797 result = new(zone()) Property(isolate(), result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002798 Expect(Token::RBRACK, CHECK_OK);
2799 break;
2800 }
2801
2802 case Token::LPAREN: {
Ben Murdoch85b71792012-04-11 18:30:58 +01002803 int pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002804 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2805
2806 // Keep track of eval() calls since they disable all local variable
2807 // optimizations.
2808 // The calls that need special treatment are the
Ben Murdoch85b71792012-04-11 18:30:58 +01002809 // direct (i.e. not aliased) eval calls. These calls are all of the
2810 // form eval(...) with no explicit receiver object where eval is not
2811 // declared in the current scope chain.
Ben Murdochb8e0da22011-05-16 14:20:40 +01002812 // These calls are marked as potentially direct eval calls. Whether
2813 // they are actually direct calls to eval is determined at run time.
Ben Murdoch85b71792012-04-11 18:30:58 +01002814 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2815 // in the local scope chain. It only matters that it's called "eval",
2816 // is called without a receiver and it refers to the original eval
2817 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002818 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01002819 if (callee != NULL &&
2820 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Ben Murdoch85b71792012-04-11 18:30:58 +01002821 Handle<String> name = callee->name();
2822 Variable* var = top_scope_->Lookup(name);
2823 if (var == NULL) {
2824 top_scope_->DeclarationScope()->RecordEvalCall();
2825 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002826 }
Ben Murdoch85b71792012-04-11 18:30:58 +01002827 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002828 break;
2829 }
2830
2831 case Token::PERIOD: {
2832 Consume(Token::PERIOD);
2833 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002834 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002835 result = new(zone()) Property(isolate(),
2836 result,
2837 NewLiteral(name),
2838 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002839 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002840 break;
2841 }
2842
2843 default:
2844 return result;
2845 }
2846 }
2847}
2848
2849
Steve Blocka7e24c12009-10-30 11:49:00 +00002850Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2851 // NewExpression ::
2852 // ('new')+ MemberExpression
2853
2854 // The grammar for new expressions is pretty warped. The keyword
2855 // 'new' can either be a part of the new expression (where it isn't
2856 // followed by an argument list) or a part of the member expression,
2857 // where it must be followed by an argument list. To accommodate
2858 // this, we parse the 'new' keywords greedily and keep track of how
2859 // many we have parsed. This information is then passed on to the
2860 // member expression parser, which is only allowed to match argument
2861 // lists as long as it has 'new' prefixes left
2862 Expect(Token::NEW, CHECK_OK);
2863 PositionStack::Element pos(stack, scanner().location().beg_pos);
2864
2865 Expression* result;
2866 if (peek() == Token::NEW) {
2867 result = ParseNewPrefix(stack, CHECK_OK);
2868 } else {
2869 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2870 }
2871
2872 if (!stack->is_empty()) {
2873 int last = stack->pop();
Ben Murdoch85b71792012-04-11 18:30:58 +01002874 result = new(zone()) CallNew(isolate(),
2875 result,
2876 new(zone()) ZoneList<Expression*>(0),
2877 last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002878 }
2879 return result;
2880}
2881
2882
2883Expression* Parser::ParseNewExpression(bool* ok) {
2884 PositionStack stack(ok);
2885 return ParseNewPrefix(&stack, ok);
2886}
2887
2888
2889Expression* Parser::ParseMemberExpression(bool* ok) {
2890 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2891}
2892
2893
2894Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2895 bool* ok) {
2896 // MemberExpression ::
2897 // (PrimaryExpression | FunctionLiteral)
2898 // ('[' Expression ']' | '.' Identifier | Arguments)*
2899
2900 // Parse the initial primary or function expression.
2901 Expression* result = NULL;
2902 if (peek() == Token::FUNCTION) {
2903 Expect(Token::FUNCTION, CHECK_OK);
2904 int function_token_position = scanner().location().beg_pos;
2905 Handle<String> name;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002906 bool is_strict_reserved_name = false;
Steve Block1e0659c2011-05-24 12:43:12 +01002907 if (peek_any_identifier()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002908 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
2909 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002910 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002911 FunctionLiteral::Type type = name.is_null()
2912 ? FunctionLiteral::ANONYMOUS_EXPRESSION
2913 : FunctionLiteral::NAMED_EXPRESSION;
2914 result = ParseFunctionLiteral(name,
2915 is_strict_reserved_name,
2916 function_token_position,
2917 type,
2918 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002919 } else {
2920 result = ParsePrimaryExpression(CHECK_OK);
2921 }
2922
2923 while (true) {
2924 switch (peek()) {
2925 case Token::LBRACK: {
2926 Consume(Token::LBRACK);
2927 int pos = scanner().location().beg_pos;
2928 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002929 result = new(zone()) Property(isolate(), result, index, pos);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002930 if (fni_ != NULL) {
2931 if (index->IsPropertyName()) {
2932 fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
2933 } else {
2934 fni_->PushLiteralName(
2935 isolate()->factory()->anonymous_function_symbol());
2936 }
2937 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002938 Expect(Token::RBRACK, CHECK_OK);
2939 break;
2940 }
2941 case Token::PERIOD: {
2942 Consume(Token::PERIOD);
2943 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002944 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002945 result = new(zone()) Property(isolate(),
2946 result,
2947 NewLiteral(name),
2948 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002949 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002950 break;
2951 }
2952 case Token::LPAREN: {
2953 if ((stack == NULL) || stack->is_empty()) return result;
2954 // Consume one of the new prefixes (already parsed).
2955 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2956 int last = stack->pop();
Ben Murdoch85b71792012-04-11 18:30:58 +01002957 result = new(zone()) CallNew(isolate(), result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002958 break;
2959 }
2960 default:
2961 return result;
2962 }
2963 }
2964}
2965
2966
2967DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2968 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2969 // contexts this is used as a statement which invokes the debugger as i a
2970 // break point is present.
2971 // DebuggerStatement ::
2972 // 'debugger' ';'
2973
2974 Expect(Token::DEBUGGER, CHECK_OK);
2975 ExpectSemicolon(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01002976 return new(zone()) DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002977}
2978
2979
2980void Parser::ReportUnexpectedToken(Token::Value token) {
2981 // We don't report stack overflows here, to avoid increasing the
2982 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002983 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002984 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002985 // Four of the tokens are treated specially
2986 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002987 case Token::EOS:
2988 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2989 case Token::NUMBER:
2990 return ReportMessage("unexpected_token_number",
2991 Vector<const char*>::empty());
2992 case Token::STRING:
2993 return ReportMessage("unexpected_token_string",
2994 Vector<const char*>::empty());
2995 case Token::IDENTIFIER:
2996 return ReportMessage("unexpected_token_identifier",
2997 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002998 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002999 return ReportMessage("unexpected_reserved",
3000 Vector<const char*>::empty());
3001 case Token::FUTURE_STRICT_RESERVED_WORD:
Ben Murdoch85b71792012-04-11 18:30:58 +01003002 return ReportMessage(top_scope_->is_strict_mode() ?
3003 "unexpected_strict_reserved" :
3004 "unexpected_token_identifier",
Steve Block1e0659c2011-05-24 12:43:12 +01003005 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003006 default:
3007 const char* name = Token::String(token);
3008 ASSERT(name != NULL);
3009 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00003010 }
3011}
3012
3013
Leon Clarkeac952652010-07-15 11:15:24 +01003014void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003015 SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
Leon Clarkeac952652010-07-15 11:15:24 +01003016 const char* element[1] = { *name_string };
3017 ReportMessage("invalid_preparser_data",
3018 Vector<const char*>(element, 1));
3019 *ok = false;
3020}
3021
3022
Steve Blocka7e24c12009-10-30 11:49:00 +00003023Expression* Parser::ParsePrimaryExpression(bool* ok) {
3024 // PrimaryExpression ::
3025 // 'this'
3026 // 'null'
3027 // 'true'
3028 // 'false'
3029 // Identifier
3030 // Number
3031 // String
3032 // ArrayLiteral
3033 // ObjectLiteral
3034 // RegExpLiteral
3035 // '(' Expression ')'
3036
3037 Expression* result = NULL;
3038 switch (peek()) {
3039 case Token::THIS: {
3040 Consume(Token::THIS);
Ben Murdoch85b71792012-04-11 18:30:58 +01003041 result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003042 break;
3043 }
3044
3045 case Token::NULL_LITERAL:
3046 Consume(Token::NULL_LITERAL);
Ben Murdoch85b71792012-04-11 18:30:58 +01003047 result = new(zone()) Literal(
3048 isolate(), isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003049 break;
3050
3051 case Token::TRUE_LITERAL:
3052 Consume(Token::TRUE_LITERAL);
Ben Murdoch85b71792012-04-11 18:30:58 +01003053 result = new(zone()) Literal(
3054 isolate(), isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003055 break;
3056
3057 case Token::FALSE_LITERAL:
3058 Consume(Token::FALSE_LITERAL);
Ben Murdoch85b71792012-04-11 18:30:58 +01003059 result = new(zone()) Literal(
3060 isolate(), isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003061 break;
3062
Steve Block1e0659c2011-05-24 12:43:12 +01003063 case Token::IDENTIFIER:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003064 case Token::FUTURE_STRICT_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003065 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003066 if (fni_ != NULL) fni_->PushVariableName(name);
Ben Murdoch85b71792012-04-11 18:30:58 +01003067 result = top_scope_->NewUnresolved(name,
3068 inside_with(),
3069 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003070 break;
3071 }
3072
3073 case Token::NUMBER: {
3074 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003075 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003076 double value = StringToDouble(isolate()->unicode_cache(),
3077 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003078 ALLOW_HEX | ALLOW_OCTALS);
Ben Murdoch85b71792012-04-11 18:30:58 +01003079 result = NewNumberLiteral(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003080 break;
3081 }
3082
3083 case Token::STRING: {
3084 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003085 Handle<String> symbol = GetSymbol(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01003086 result = NewLiteral(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003087 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00003088 break;
3089 }
3090
3091 case Token::ASSIGN_DIV:
3092 result = ParseRegExpLiteral(true, CHECK_OK);
3093 break;
3094
3095 case Token::DIV:
3096 result = ParseRegExpLiteral(false, CHECK_OK);
3097 break;
3098
3099 case Token::LBRACK:
3100 result = ParseArrayLiteral(CHECK_OK);
3101 break;
3102
3103 case Token::LBRACE:
3104 result = ParseObjectLiteral(CHECK_OK);
3105 break;
3106
3107 case Token::LPAREN:
3108 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003109 // Heuristically try to detect immediately called functions before
3110 // seeing the call parentheses.
3111 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00003112 result = ParseExpression(true, CHECK_OK);
3113 Expect(Token::RPAREN, CHECK_OK);
3114 break;
3115
3116 case Token::MOD:
3117 if (allow_natives_syntax_ || extension_ != NULL) {
3118 result = ParseV8Intrinsic(CHECK_OK);
3119 break;
3120 }
3121 // If we're not allowing special syntax we fall-through to the
3122 // default case.
3123
3124 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01003125 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00003126 ReportUnexpectedToken(tok);
3127 *ok = false;
3128 return NULL;
3129 }
3130 }
3131
3132 return result;
3133}
3134
3135
Leon Clarke4515c472010-02-03 11:58:03 +00003136void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
3137 Handle<FixedArray> literals,
3138 bool* is_simple,
3139 int* depth) {
3140 // Fill in the literals.
3141 // Accumulate output values in local variables.
3142 bool is_simple_acc = true;
3143 int depth_acc = 1;
3144 for (int i = 0; i < values->length(); i++) {
3145 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
3146 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3147 depth_acc = m_literal->depth() + 1;
3148 }
3149 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3150 if (boilerplate_value->IsUndefined()) {
3151 literals->set_the_hole(i);
3152 is_simple_acc = false;
3153 } else {
3154 literals->set(i, *boilerplate_value);
3155 }
3156 }
3157
3158 *is_simple = is_simple_acc;
3159 *depth = depth_acc;
3160}
3161
3162
Steve Blocka7e24c12009-10-30 11:49:00 +00003163Expression* Parser::ParseArrayLiteral(bool* ok) {
3164 // ArrayLiteral ::
3165 // '[' Expression? (',' Expression?)* ']'
3166
Ben Murdoch257744e2011-11-30 15:57:28 +00003167 ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003168 Expect(Token::LBRACK, CHECK_OK);
3169 while (peek() != Token::RBRACK) {
3170 Expression* elem;
3171 if (peek() == Token::COMMA) {
3172 elem = GetLiteralTheHole();
3173 } else {
3174 elem = ParseAssignmentExpression(true, CHECK_OK);
3175 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003176 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00003177 if (peek() != Token::RBRACK) {
3178 Expect(Token::COMMA, CHECK_OK);
3179 }
3180 }
3181 Expect(Token::RBRACK, CHECK_OK);
3182
3183 // Update the scope information before the pre-parsing bailout.
Ben Murdoch85b71792012-04-11 18:30:58 +01003184 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003185
Ben Murdoch85b71792012-04-11 18:30:58 +01003186 // Allocate a fixed array with all the literals.
3187 Handle<FixedArray> literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003188 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003189
3190 // Fill in the literals.
3191 bool is_simple = true;
3192 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003193 for (int i = 0, n = values->length(); i < n; i++) {
3194 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003195 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3196 depth = m_literal->depth() + 1;
3197 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003198 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003199 if (boilerplate_value->IsUndefined()) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003200 literals->set_the_hole(i);
Steve Blocka7e24c12009-10-30 11:49:00 +00003201 is_simple = false;
3202 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +01003203 literals->set(i, *boilerplate_value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003204 }
3205 }
3206
Iain Merrick75681382010-08-19 15:07:18 +01003207 // Simple and shallow arrays can be lazily copied, we transform the
3208 // elements array to a copy-on-write array.
Ben Murdoch85b71792012-04-11 18:30:58 +01003209 if (is_simple && depth == 1 && values->length() > 0) {
3210 literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003211 }
3212
Ben Murdoch85b71792012-04-11 18:30:58 +01003213 return new(zone()) ArrayLiteral(
3214 isolate(), literals, values, literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003215}
3216
3217
3218bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3219 return property != NULL &&
3220 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3221}
3222
3223
3224bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003225 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003226 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3227 return lit != NULL && lit->is_simple();
3228}
3229
Iain Merrick75681382010-08-19 15:07:18 +01003230
3231bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3232 Expression* value) {
3233 // If value is a literal the property value is already set in the
3234 // boilerplate object.
3235 if (value->AsLiteral() != NULL) return false;
3236 // If value is a materialized literal the property value is already set
3237 // in the boilerplate object if it is simple.
3238 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3239 return true;
3240}
3241
3242
Steve Blocka7e24c12009-10-30 11:49:00 +00003243Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3244 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003245 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003246 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3247 if (object_literal != NULL) {
3248 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003249 if (object_literal->fast_elements()) {
3250 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3251 } else {
3252 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3253 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003254 result->set(kElementsSlot, *object_literal->constant_properties());
3255 } else {
3256 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3257 ASSERT(array_literal != NULL && array_literal->is_simple());
3258 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003259 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003260 }
3261 return result;
3262}
3263
3264
3265CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3266 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3267 return static_cast<Type>(type_value->value());
3268}
3269
3270
3271Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3272 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3273}
3274
3275
3276Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3277 if (expression->AsLiteral() != NULL) {
3278 return expression->AsLiteral()->handle();
3279 }
3280 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3281 return CompileTimeValue::GetValue(expression);
3282 }
Steve Block44f0eee2011-05-26 01:26:41 +01003283 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003284}
3285
Ben Murdoch85b71792012-04-11 18:30:58 +01003286// Defined in ast.cc
3287bool IsEqualString(void* first, void* second);
3288bool IsEqualNumber(void* first, void* second);
3289
3290
Steve Block1e0659c2011-05-24 12:43:12 +01003291// Validation per 11.1.5 Object Initialiser
3292class ObjectLiteralPropertyChecker {
3293 public:
Ben Murdoch85b71792012-04-11 18:30:58 +01003294 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3295 props(&IsEqualString),
3296 elems(&IsEqualNumber),
Steve Block1e0659c2011-05-24 12:43:12 +01003297 parser_(parser),
Ben Murdoch85b71792012-04-11 18:30:58 +01003298 strict_(strict) {
Steve Block1e0659c2011-05-24 12:43:12 +01003299 }
3300
3301 void CheckProperty(
3302 ObjectLiteral::Property* property,
3303 Scanner::Location loc,
3304 bool* ok);
3305
3306 private:
3307 enum PropertyKind {
3308 kGetAccessor = 0x01,
3309 kSetAccessor = 0x02,
3310 kAccessor = kGetAccessor | kSetAccessor,
3311 kData = 0x04
3312 };
3313
3314 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3315 switch (property->kind()) {
3316 case ObjectLiteral::Property::GETTER:
3317 return kGetAccessor;
3318 case ObjectLiteral::Property::SETTER:
3319 return kSetAccessor;
3320 default:
3321 return kData;
3322 }
3323 }
3324
Ben Murdoch85b71792012-04-11 18:30:58 +01003325 HashMap props;
3326 HashMap elems;
Steve Block1e0659c2011-05-24 12:43:12 +01003327 Parser* parser_;
Ben Murdoch85b71792012-04-11 18:30:58 +01003328 bool strict_;
Steve Block1e0659c2011-05-24 12:43:12 +01003329};
3330
3331
3332void ObjectLiteralPropertyChecker::CheckProperty(
3333 ObjectLiteral::Property* property,
3334 Scanner::Location loc,
3335 bool* ok) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003336
Steve Block1e0659c2011-05-24 12:43:12 +01003337 ASSERT(property != NULL);
Ben Murdoch85b71792012-04-11 18:30:58 +01003338
3339 Literal *lit = property->key();
3340 Handle<Object> handle = lit->handle();
3341
3342 uint32_t hash;
3343 HashMap* map;
3344 void* key;
3345
3346 if (handle->IsSymbol()) {
3347 Handle<String> name(String::cast(*handle));
3348 if (name->AsArrayIndex(&hash)) {
3349 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
3350 key = key_handle.location();
3351 map = &elems;
3352 } else {
3353 key = handle.location();
3354 hash = name->Hash();
3355 map = &props;
3356 }
3357 } else if (handle->ToArrayIndex(&hash)) {
3358 key = handle.location();
3359 map = &elems;
3360 } else {
3361 ASSERT(handle->IsNumber());
3362 double num = handle->Number();
3363 char arr[100];
3364 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3365 const char* str = DoubleToCString(num, buffer);
3366 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
3367 key = name.location();
3368 hash = name->Hash();
3369 map = &props;
3370 }
3371
3372 // Lookup property previously defined, if any.
3373 HashMap::Entry* entry = map->Lookup(key, hash, true);
Steve Block1e0659c2011-05-24 12:43:12 +01003374 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3375 intptr_t curr = GetPropertyKind(property);
3376
Ben Murdoch85b71792012-04-11 18:30:58 +01003377 // Duplicate data properties are illegal in strict mode.
3378 if (strict_ && (curr & prev & kData) != 0) {
Steve Block1e0659c2011-05-24 12:43:12 +01003379 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3380 Vector<const char*>::empty());
3381 *ok = false;
3382 return;
3383 }
3384 // Data property conflicting with an accessor.
3385 if (((curr & kData) && (prev & kAccessor)) ||
3386 ((prev & kData) && (curr & kAccessor))) {
3387 parser_->ReportMessageAt(loc, "accessor_data_property",
3388 Vector<const char*>::empty());
3389 *ok = false;
3390 return;
3391 }
3392 // Two accessors of the same type conflicting
3393 if ((curr & prev & kAccessor) != 0) {
3394 parser_->ReportMessageAt(loc, "accessor_get_set",
3395 Vector<const char*>::empty());
3396 *ok = false;
3397 return;
3398 }
3399
3400 // Update map
3401 entry->value = reinterpret_cast<void*> (prev | curr);
3402 *ok = true;
3403}
3404
Steve Blocka7e24c12009-10-30 11:49:00 +00003405
Leon Clarke4515c472010-02-03 11:58:03 +00003406void Parser::BuildObjectLiteralConstantProperties(
3407 ZoneList<ObjectLiteral::Property*>* properties,
3408 Handle<FixedArray> constant_properties,
3409 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003410 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003411 int* depth) {
3412 int position = 0;
3413 // Accumulate the value in local variables and store it at the end.
3414 bool is_simple_acc = true;
3415 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003416 uint32_t max_element_index = 0;
3417 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003418 for (int i = 0; i < properties->length(); i++) {
3419 ObjectLiteral::Property* property = properties->at(i);
3420 if (!IsBoilerplateProperty(property)) {
3421 is_simple_acc = false;
3422 continue;
3423 }
3424 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3425 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3426 depth_acc = m_literal->depth() + 1;
3427 }
3428
3429 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3430 // value for COMPUTED properties, the real value is filled in at
3431 // runtime. The enumeration order is maintained.
3432 Handle<Object> key = property->key()->handle();
3433 Handle<Object> value = GetBoilerplateValue(property->value());
3434 is_simple_acc = is_simple_acc && !value->IsUndefined();
3435
Steve Block6ded16b2010-05-10 14:33:55 +01003436 // Keep track of the number of elements in the object literal and
3437 // the largest element index. If the largest element index is
3438 // much larger than the number of elements, creating an object
3439 // literal with fast elements will be a waste of space.
3440 uint32_t element_index = 0;
3441 if (key->IsString()
3442 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3443 && element_index > max_element_index) {
3444 max_element_index = element_index;
3445 elements++;
3446 } else if (key->IsSmi()) {
3447 int key_value = Smi::cast(*key)->value();
3448 if (key_value > 0
3449 && static_cast<uint32_t>(key_value) > max_element_index) {
3450 max_element_index = key_value;
3451 }
3452 elements++;
3453 }
3454
Leon Clarke4515c472010-02-03 11:58:03 +00003455 // Add name, value pair to the fixed array.
3456 constant_properties->set(position++, *key);
3457 constant_properties->set(position++, *value);
3458 }
Steve Block6ded16b2010-05-10 14:33:55 +01003459 *fast_elements =
3460 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003461 *is_simple = is_simple_acc;
3462 *depth = depth_acc;
3463}
3464
3465
Ben Murdochbb769b22010-08-11 14:56:33 +01003466ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3467 bool* ok) {
3468 // Special handling of getter and setter syntax:
3469 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3470 // We have already read the "get" or "set" keyword.
3471 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003472 bool is_keyword = Token::IsKeyword(next);
3473 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003474 next == Token::FUTURE_RESERVED_WORD ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003475 next == Token::FUTURE_STRICT_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003476 next == Token::STRING || is_keyword) {
3477 Handle<String> name;
3478 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003479 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003480 } else {
3481 name = GetSymbol(CHECK_OK);
3482 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003483 FunctionLiteral* value =
3484 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003485 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003486 RelocInfo::kNoPosition,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003487 FunctionLiteral::ANONYMOUS_EXPRESSION,
Ben Murdochbb769b22010-08-11 14:56:33 +01003488 CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01003489 // Allow any number of parameters for compatiabilty with JSC.
Steve Block9fac8402011-05-12 15:51:54 +01003490 // Specification only allows zero parameters for get and one for set.
Ben Murdoch85b71792012-04-11 18:30:58 +01003491 ObjectLiteral::Property* property =
3492 new(zone()) ObjectLiteral::Property(is_getter, value);
3493 return property;
Ben Murdochbb769b22010-08-11 14:56:33 +01003494 } else {
3495 ReportUnexpectedToken(next);
3496 *ok = false;
3497 return NULL;
3498 }
3499}
3500
3501
Steve Blocka7e24c12009-10-30 11:49:00 +00003502Expression* Parser::ParseObjectLiteral(bool* ok) {
3503 // ObjectLiteral ::
3504 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003505 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3506 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003507 // )*[','] '}'
3508
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003509 ZoneList<ObjectLiteral::Property*>* properties =
Ben Murdoch257744e2011-11-30 15:57:28 +00003510 new(zone()) ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003511 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003512 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003513
Ben Murdoch85b71792012-04-11 18:30:58 +01003514 ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003515
Steve Blocka7e24c12009-10-30 11:49:00 +00003516 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003517
Steve Blocka7e24c12009-10-30 11:49:00 +00003518 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003519 if (fni_ != NULL) fni_->Enter();
3520
Steve Blocka7e24c12009-10-30 11:49:00 +00003521 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003522 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003523
3524 // Location of the property name token
3525 Scanner::Location loc = scanner().peek_location();
3526
Ben Murdochbb769b22010-08-11 14:56:33 +01003527 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003528 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003529 case Token::FUTURE_STRICT_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003530 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003531 bool is_getter = false;
3532 bool is_setter = false;
3533 Handle<String> id =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003534 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003535 if (fni_ != NULL) fni_->PushLiteralName(id);
3536
Ben Murdochbb769b22010-08-11 14:56:33 +01003537 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003538 // Update loc to point to the identifier
3539 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003540 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003541 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3542 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003543 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003544 }
Steve Block1e0659c2011-05-24 12:43:12 +01003545 // Validate the property.
3546 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003547 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003548 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003549
3550 if (fni_ != NULL) {
3551 fni_->Infer();
3552 fni_->Leave();
3553 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003554 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003555 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003556 // Failed to parse as get/set property, so it's just a property
3557 // called "get" or "set".
Ben Murdoch85b71792012-04-11 18:30:58 +01003558 key = NewLiteral(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003559 break;
3560 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003561 case Token::STRING: {
3562 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003563 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003564 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003565 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003566 if (!string.is_null() && string->AsArrayIndex(&index)) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003567 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003568 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003569 }
Ben Murdoch85b71792012-04-11 18:30:58 +01003570 key = NewLiteral(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003571 break;
3572 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003573 case Token::NUMBER: {
3574 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003575 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003576 double value = StringToDouble(isolate()->unicode_cache(),
3577 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003578 ALLOW_HEX | ALLOW_OCTALS);
Ben Murdoch85b71792012-04-11 18:30:58 +01003579 key = NewNumberLiteral(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003580 break;
3581 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003582 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003583 if (Token::IsKeyword(next)) {
3584 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003585 Handle<String> string = GetSymbol(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01003586 key = NewLiteral(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003587 } else {
3588 // Unexpected token.
3589 Token::Value next = Next();
3590 ReportUnexpectedToken(next);
3591 *ok = false;
3592 return NULL;
3593 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003594 }
3595
3596 Expect(Token::COLON, CHECK_OK);
3597 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3598
3599 ObjectLiteral::Property* property =
Ben Murdoch85b71792012-04-11 18:30:58 +01003600 new(zone()) ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003601
Ben Murdoch85b71792012-04-11 18:30:58 +01003602 // Mark object literals that contain function literals and pretenure the
3603 // literal so it can be added as a constant function property.
3604 if (value->AsFunctionLiteral() != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +01003605 has_function = true;
Ben Murdoch85b71792012-04-11 18:30:58 +01003606 value->AsFunctionLiteral()->set_pretenure(true);
Steve Block44f0eee2011-05-26 01:26:41 +01003607 }
3608
Steve Blocka7e24c12009-10-30 11:49:00 +00003609 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3610 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003611 // Validate the property
3612 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003613 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003614
3615 // TODO(1240767): Consider allowing trailing comma.
3616 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003617
3618 if (fni_ != NULL) {
3619 fni_->Infer();
3620 fni_->Leave();
3621 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003622 }
3623 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003624
Steve Blocka7e24c12009-10-30 11:49:00 +00003625 // Computation of literal_index must happen before pre parse bailout.
Ben Murdoch85b71792012-04-11 18:30:58 +01003626 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003627
Steve Block44f0eee2011-05-26 01:26:41 +01003628 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3629 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003630
Steve Blocka7e24c12009-10-30 11:49:00 +00003631 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003632 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003633 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003634 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003635 constant_properties,
3636 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003637 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003638 &depth);
Ben Murdoch85b71792012-04-11 18:30:58 +01003639 return new(zone()) ObjectLiteral(isolate(),
3640 constant_properties,
3641 properties,
3642 literal_index,
3643 is_simple,
3644 fast_elements,
3645 depth,
3646 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003647}
3648
3649
3650Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003651 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003652 Next();
3653 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3654 *ok = false;
3655 return NULL;
3656 }
3657
Ben Murdoch85b71792012-04-11 18:30:58 +01003658 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003659
Steve Block9fac8402011-05-12 15:51:54 +01003660 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003661 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003662 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003663 Next();
3664
Ben Murdoch85b71792012-04-11 18:30:58 +01003665 return new(zone()) RegExpLiteral(
3666 isolate(), js_pattern, js_flags, literal_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003667}
3668
3669
3670ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3671 // Arguments ::
3672 // '(' (AssignmentExpression)*[','] ')'
3673
Ben Murdoch257744e2011-11-30 15:57:28 +00003674 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003675 Expect(Token::LPAREN, CHECK_OK);
3676 bool done = (peek() == Token::RPAREN);
3677 while (!done) {
3678 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003679 result->Add(argument);
Steve Block053d10c2011-06-13 19:13:29 +01003680 if (result->length() > kMaxNumFunctionParameters) {
3681 ReportMessageAt(scanner().location(), "too_many_arguments",
3682 Vector<const char*>::empty());
3683 *ok = false;
3684 return NULL;
3685 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003686 done = (peek() == Token::RPAREN);
3687 if (!done) Expect(Token::COMMA, CHECK_OK);
3688 }
3689 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003690 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003691}
3692
3693
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003694FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
3695 bool name_is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003696 int function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003697 FunctionLiteral::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +00003698 bool* ok) {
3699 // Function ::
3700 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003701
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003702 // Anonymous functions were passed either the empty symbol or a null
3703 // handle as the function name. Remember if we were passed a non-empty
3704 // handle to decide whether to invoke function name inference.
3705 bool should_infer_name = function_name.is_null();
3706
3707 // We want a non-null handle as the function name.
3708 if (should_infer_name) {
3709 function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003710 }
3711
3712 int num_parameters = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003713 // Function declarations are function scoped in normal mode, so they are
3714 // hoisted. In harmony block scoping mode they are block scoped, so they
3715 // are not hoisted.
Ben Murdoch85b71792012-04-11 18:30:58 +01003716 Scope* scope = (type == FunctionLiteral::DECLARATION &&
3717 !harmony_block_scoping_)
3718 ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false)
3719 : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3720 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8);
3721 int materialized_literal_count;
3722 int expected_property_count;
3723 int start_pos;
3724 int end_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01003725 bool only_simple_this_property_assignments;
3726 Handle<FixedArray> this_property_assignments;
Ben Murdoch85b71792012-04-11 18:30:58 +01003727 bool has_duplicate_parameters = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003728 // Parse function body.
Ben Murdoch85b71792012-04-11 18:30:58 +01003729 { LexicalScope lexical_scope(this, scope, isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003730 top_scope_->SetScopeName(function_name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003731
3732 // FormalParameterList ::
3733 // '(' (Identifier)*[','] ')'
3734 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01003735 start_pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00003736 Scanner::Location name_loc = Scanner::Location::invalid();
3737 Scanner::Location dupe_loc = Scanner::Location::invalid();
3738 Scanner::Location reserved_loc = Scanner::Location::invalid();
Steve Block1e0659c2011-05-24 12:43:12 +01003739
Steve Blocka7e24c12009-10-30 11:49:00 +00003740 bool done = (peek() == Token::RPAREN);
3741 while (!done) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003742 bool is_strict_reserved = false;
Steve Block1e0659c2011-05-24 12:43:12 +01003743 Handle<String> param_name =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003744 ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
3745 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003746
3747 // Store locations for possible future error reports.
3748 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3749 name_loc = scanner().location();
3750 }
3751 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003752 has_duplicate_parameters = true;
Steve Block1e0659c2011-05-24 12:43:12 +01003753 dupe_loc = scanner().location();
3754 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003755 if (!reserved_loc.IsValid() && is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01003756 reserved_loc = scanner().location();
3757 }
3758
Ben Murdoch85b71792012-04-11 18:30:58 +01003759 top_scope_->DeclareParameter(param_name,
3760 harmony_block_scoping_
3761 ? Variable::LET
3762 : Variable::VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003763 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003764 if (num_parameters > kMaxNumFunctionParameters) {
3765 ReportMessageAt(scanner().location(), "too_many_parameters",
3766 Vector<const char*>::empty());
3767 *ok = false;
3768 return NULL;
3769 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003770 done = (peek() == Token::RPAREN);
3771 if (!done) Expect(Token::COMMA, CHECK_OK);
3772 }
3773 Expect(Token::RPAREN, CHECK_OK);
3774
3775 Expect(Token::LBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003776
3777 // If we have a named function expression, we add a local variable
3778 // declaration to the body of the function with the name of the
3779 // function and let it refer to the function itself (closure).
3780 // NOTE: We create a proxy and resolve it here so that in the
3781 // future we can change the AST to only refer to VariableProxies
3782 // instead of Variables and Proxis as is the case now.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003783 if (type == FunctionLiteral::NAMED_EXPRESSION) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003784 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3785 VariableProxy* fproxy =
3786 top_scope_->NewUnresolved(function_name, inside_with());
3787 fproxy->BindTo(fvar);
3788 body->Add(new(zone()) ExpressionStatement(
3789 new(zone()) Assignment(isolate(),
3790 Token::INIT_CONST,
3791 fproxy,
3792 new(zone()) ThisFunction(isolate()),
3793 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003794 }
3795
Ben Murdoch85b71792012-04-11 18:30:58 +01003796 // Determine if the function will be lazily compiled. The mode can only
3797 // be PARSE_LAZILY if the --lazy flag is true. We will not lazily
3798 // compile if we do not have preparser data for the function.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003799 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3800 top_scope_->outer_scope()->is_global_scope() &&
3801 top_scope_->HasTrivialOuterContext() &&
Ben Murdoch85b71792012-04-11 18:30:58 +01003802 !parenthesized_function_ &&
3803 pre_data() != NULL);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003804 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003805
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003806 if (is_lazily_compiled) {
3807 int function_block_pos = scanner().location().beg_pos;
Ben Murdoch85b71792012-04-11 18:30:58 +01003808 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
3809 if (!entry.is_valid()) {
3810 // There is no preparser data for the function, we will not lazily
3811 // compile after all.
3812 is_lazily_compiled = false;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003813 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +01003814 end_pos = entry.end_pos();
3815 if (end_pos <= function_block_pos) {
3816 // End position greater than end of stream is safe, and hard to check.
3817 ReportInvalidPreparseData(function_name, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003818 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003819 isolate()->counters()->total_preparse_skipped()->Increment(
Ben Murdoch85b71792012-04-11 18:30:58 +01003820 end_pos - function_block_pos);
3821 // Seek to position just before terminal '}'.
3822 scanner().SeekForward(end_pos - 1);
3823 materialized_literal_count = entry.literal_count();
3824 expected_property_count = entry.property_count();
3825 if (entry.strict_mode()) top_scope_->EnableStrictMode();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003826 only_simple_this_property_assignments = false;
3827 this_property_assignments = isolate()->factory()->empty_fixed_array();
Ben Murdoch85b71792012-04-11 18:30:58 +01003828 Expect(Token::RBRACE, CHECK_OK);
Leon Clarkeac952652010-07-15 11:15:24 +01003829 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003830 }
3831
3832 if (!is_lazily_compiled) {
Ben Murdoch85b71792012-04-11 18:30:58 +01003833 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003834
Ben Murdoch85b71792012-04-11 18:30:58 +01003835 materialized_literal_count = lexical_scope.materialized_literal_count();
3836 expected_property_count = lexical_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003837 only_simple_this_property_assignments =
Ben Murdoch85b71792012-04-11 18:30:58 +01003838 lexical_scope.only_simple_this_property_assignments();
3839 this_property_assignments = lexical_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003840
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003841 Expect(Token::RBRACE, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01003842 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003843 }
3844
Steve Block1e0659c2011-05-24 12:43:12 +01003845 // Validate strict mode.
Ben Murdoch85b71792012-04-11 18:30:58 +01003846 if (top_scope_->is_strict_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003847 if (IsEvalOrArguments(function_name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01003848 int position = function_token_position != RelocInfo::kNoPosition
3849 ? function_token_position
3850 : (start_pos > 0 ? start_pos - 1 : start_pos);
3851 Scanner::Location location = Scanner::Location(position, start_pos);
3852 ReportMessageAt(location,
3853 "strict_function_name", Vector<const char*>::empty());
3854 *ok = false;
3855 return NULL;
3856 }
3857 if (name_loc.IsValid()) {
3858 ReportMessageAt(name_loc, "strict_param_name",
3859 Vector<const char*>::empty());
3860 *ok = false;
3861 return NULL;
3862 }
3863 if (dupe_loc.IsValid()) {
3864 ReportMessageAt(dupe_loc, "strict_param_dupe",
3865 Vector<const char*>::empty());
3866 *ok = false;
3867 return NULL;
3868 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003869 if (name_is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01003870 int position = function_token_position != RelocInfo::kNoPosition
3871 ? function_token_position
3872 : (start_pos > 0 ? start_pos - 1 : start_pos);
3873 Scanner::Location location = Scanner::Location(position, start_pos);
3874 ReportMessageAt(location, "strict_reserved_word",
3875 Vector<const char*>::empty());
3876 *ok = false;
3877 return NULL;
3878 }
3879 if (reserved_loc.IsValid()) {
3880 ReportMessageAt(reserved_loc, "strict_reserved_word",
3881 Vector<const char*>::empty());
3882 *ok = false;
3883 return NULL;
3884 }
Ben Murdoch85b71792012-04-11 18:30:58 +01003885 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003886 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003887 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01003888
Ben Murdoch85b71792012-04-11 18:30:58 +01003889 if (harmony_block_scoping_) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003890 CheckConflictingVarDeclarations(scope, CHECK_OK);
3891 }
3892
Ben Murdoch8b112d22011-06-08 16:22:53 +01003893 FunctionLiteral* function_literal =
Ben Murdoch85b71792012-04-11 18:30:58 +01003894 new(zone()) FunctionLiteral(isolate(),
3895 function_name,
3896 scope,
3897 body,
3898 materialized_literal_count,
3899 expected_property_count,
3900 only_simple_this_property_assignments,
3901 this_property_assignments,
3902 num_parameters,
3903 start_pos,
3904 end_pos,
3905 type,
3906 has_duplicate_parameters);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003907 function_literal->set_function_token_position(function_token_position);
3908
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003909 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003910 return function_literal;
Steve Blocka7e24c12009-10-30 11:49:00 +00003911}
3912
3913
3914Expression* Parser::ParseV8Intrinsic(bool* ok) {
3915 // CallRuntime ::
3916 // '%' Identifier Arguments
3917
3918 Expect(Token::MOD, CHECK_OK);
3919 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003920 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003921
3922 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003923 // The extension structures are only accessible while parsing the
3924 // very first time not when reparsing because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003925 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00003926 }
3927
Steve Block44f0eee2011-05-26 01:26:41 +01003928 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003929
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003930 // Check for built-in IS_VAR macro.
3931 if (function != NULL &&
3932 function->intrinsic_type == Runtime::RUNTIME &&
3933 function->function_id == Runtime::kIS_VAR) {
3934 // %IS_VAR(x) evaluates to x if x is a variable,
3935 // leads to a parse error otherwise. Could be implemented as an
3936 // inline function %_IS_VAR(x) to eliminate this special case.
3937 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3938 return args->at(0);
3939 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003940 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003941 *ok = false;
3942 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003943 }
3944 }
3945
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003946 // Check that the expected number of arguments are being passed.
3947 if (function != NULL &&
3948 function->nargs != -1 &&
3949 function->nargs != args->length()) {
3950 ReportMessage("illegal_access", Vector<const char*>::empty());
3951 *ok = false;
3952 return NULL;
3953 }
3954
3955 // We have a valid intrinsics call or a call to a builtin.
Ben Murdoch85b71792012-04-11 18:30:58 +01003956 return new(zone()) CallRuntime(isolate(), name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003957}
3958
3959
Steve Block1e0659c2011-05-24 12:43:12 +01003960bool Parser::peek_any_identifier() {
3961 Token::Value next = peek();
3962 return next == Token::IDENTIFIER ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003963 next == Token::FUTURE_RESERVED_WORD ||
3964 next == Token::FUTURE_STRICT_RESERVED_WORD;
Steve Block1e0659c2011-05-24 12:43:12 +01003965}
3966
3967
Steve Blocka7e24c12009-10-30 11:49:00 +00003968void Parser::Consume(Token::Value token) {
3969 Token::Value next = Next();
3970 USE(next);
3971 USE(token);
3972 ASSERT(next == token);
3973}
3974
3975
3976void Parser::Expect(Token::Value token, bool* ok) {
3977 Token::Value next = Next();
3978 if (next == token) return;
3979 ReportUnexpectedToken(next);
3980 *ok = false;
3981}
3982
3983
Leon Clarke4515c472010-02-03 11:58:03 +00003984bool Parser::Check(Token::Value token) {
3985 Token::Value next = peek();
3986 if (next == token) {
3987 Consume(next);
3988 return true;
3989 }
3990 return false;
3991}
3992
3993
Steve Blocka7e24c12009-10-30 11:49:00 +00003994void Parser::ExpectSemicolon(bool* ok) {
3995 // Check for automatic semicolon insertion according to
3996 // the rules given in ECMA-262, section 7.9, page 21.
3997 Token::Value tok = peek();
3998 if (tok == Token::SEMICOLON) {
3999 Next();
4000 return;
4001 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004002 if (scanner().HasAnyLineTerminatorBeforeNext() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00004003 tok == Token::RBRACE ||
4004 tok == Token::EOS) {
4005 return;
4006 }
4007 Expect(Token::SEMICOLON, ok);
4008}
4009
4010
4011Literal* Parser::GetLiteralUndefined() {
Ben Murdoch85b71792012-04-11 18:30:58 +01004012 return NewLiteral(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00004013}
4014
4015
4016Literal* Parser::GetLiteralTheHole() {
Ben Murdoch85b71792012-04-11 18:30:58 +01004017 return NewLiteral(isolate()->factory()->the_hole_value());
4018}
4019
4020
4021Literal* Parser::GetLiteralNumber(double value) {
4022 return NewNumberLiteral(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00004023}
4024
4025
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004026// Parses an identifier that is valid for the current scope, in particular it
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004027// fails on strict mode future reserved keywords in a strict scope.
Steve Blocka7e24c12009-10-30 11:49:00 +00004028Handle<String> Parser::ParseIdentifier(bool* ok) {
Ben Murdoch85b71792012-04-11 18:30:58 +01004029 if (top_scope_->is_strict_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004030 Expect(Token::IDENTIFIER, ok);
4031 } else if (!Check(Token::IDENTIFIER)) {
4032 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4033 }
4034 if (!*ok) return Handle<String>();
4035 return GetSymbol(ok);
Steve Block1e0659c2011-05-24 12:43:12 +01004036}
4037
4038
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004039// Parses and identifier or a strict mode future reserved word, and indicate
4040// whether it is strict mode future reserved.
4041Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
4042 bool* is_strict_reserved, bool* ok) {
4043 *is_strict_reserved = false;
4044 if (!Check(Token::IDENTIFIER)) {
4045 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4046 *is_strict_reserved = true;
Steve Block1e0659c2011-05-24 12:43:12 +01004047 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004048 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01004049 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004050}
4051
Ben Murdochbb769b22010-08-11 14:56:33 +01004052
4053Handle<String> Parser::ParseIdentifierName(bool* ok) {
4054 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01004055 if (next != Token::IDENTIFIER &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004056 next != Token::FUTURE_RESERVED_WORD &&
4057 next != Token::FUTURE_STRICT_RESERVED_WORD &&
4058 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01004059 ReportUnexpectedToken(next);
4060 *ok = false;
4061 return Handle<String>();
4062 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01004063 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01004064}
4065
4066
Steve Block1e0659c2011-05-24 12:43:12 +01004067// Checks LHS expression for assignment and prefix/postfix increment/decrement
4068// in strict mode.
4069void Parser::CheckStrictModeLValue(Expression* expression,
4070 const char* error,
4071 bool* ok) {
Ben Murdoch85b71792012-04-11 18:30:58 +01004072 ASSERT(top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01004073 VariableProxy* lhs = expression != NULL
4074 ? expression->AsVariableProxy()
4075 : NULL;
4076
4077 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
4078 ReportMessage(error, Vector<const char*>::empty());
4079 *ok = false;
4080 }
4081}
4082
4083
Ben Murdoch257744e2011-11-30 15:57:28 +00004084// Checks whether an octal literal was last seen between beg_pos and end_pos.
4085// If so, reports an error. Only called for strict mode.
Steve Block1e0659c2011-05-24 12:43:12 +01004086void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004087 Scanner::Location octal = scanner().octal_position();
4088 if (octal.IsValid() &&
4089 beg_pos <= octal.beg_pos &&
4090 octal.end_pos <= end_pos) {
4091 ReportMessageAt(octal, "strict_octal_literal",
Steve Block1e0659c2011-05-24 12:43:12 +01004092 Vector<const char*>::empty());
4093 scanner().clear_octal_position();
4094 *ok = false;
4095 }
4096}
4097
4098
Ben Murdoch589d6972011-11-30 16:04:58 +00004099void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4100 Declaration* decl = scope->CheckConflictingVarDeclarations();
4101 if (decl != NULL) {
4102 // In harmony mode we treat conflicting variable bindinds as early
4103 // errors. See ES5 16 for a definition of early errors.
4104 Handle<String> name = decl->proxy()->name();
4105 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
4106 const char* elms[2] = { "Variable", *c_string };
4107 Vector<const char*> args(elms, 2);
4108 int position = decl->proxy()->position();
4109 Scanner::Location location = position == RelocInfo::kNoPosition
4110 ? Scanner::Location::invalid()
4111 : Scanner::Location(position, position + 1);
4112 ReportMessageAt(location, "redeclaration", args);
4113 *ok = false;
4114 }
4115}
4116
4117
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004118// This function reads an identifier name and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01004119// is 'get' or 'set'.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004120Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
4121 bool* is_set,
4122 bool* ok) {
4123 Handle<String> result = ParseIdentifierName(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004124 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01004125 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
4126 const char* token = scanner().literal_ascii_string().start();
4127 *is_get = strncmp(token, "get", 3) == 0;
4128 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00004129 }
Steve Block1e0659c2011-05-24 12:43:12 +01004130 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00004131}
4132
4133
4134// ----------------------------------------------------------------------------
4135// Parser support
4136
4137
4138bool Parser::TargetStackContainsLabel(Handle<String> label) {
4139 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4140 BreakableStatement* stat = t->node()->AsBreakableStatement();
4141 if (stat != NULL && ContainsLabel(stat->labels(), label))
4142 return true;
4143 }
4144 return false;
4145}
4146
4147
4148BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
4149 bool anonymous = label.is_null();
4150 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4151 BreakableStatement* stat = t->node()->AsBreakableStatement();
4152 if (stat == NULL) continue;
4153 if ((anonymous && stat->is_target_for_anonymous()) ||
4154 (!anonymous && ContainsLabel(stat->labels(), label))) {
4155 RegisterTargetUse(stat->break_target(), t->previous());
4156 return stat;
4157 }
4158 }
4159 return NULL;
4160}
4161
4162
4163IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
4164 bool* ok) {
4165 bool anonymous = label.is_null();
4166 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4167 IterationStatement* stat = t->node()->AsIterationStatement();
4168 if (stat == NULL) continue;
4169
4170 ASSERT(stat->is_target_for_anonymous());
4171 if (anonymous || ContainsLabel(stat->labels(), label)) {
4172 RegisterTargetUse(stat->continue_target(), t->previous());
4173 return stat;
4174 }
4175 }
4176 return NULL;
4177}
4178
4179
Ben Murdoch8b112d22011-06-08 16:22:53 +01004180void Parser::RegisterTargetUse(Label* target, Target* stop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004181 // Register that a break target found at the given stop in the
4182 // target stack has been used from the top of the target stack. Add
4183 // the break target to any TargetCollectors passed on the stack.
4184 for (Target* t = target_stack_; t != stop; t = t->previous()) {
4185 TargetCollector* collector = t->node()->AsTargetCollector();
4186 if (collector != NULL) collector->AddTarget(target);
4187 }
4188}
4189
4190
Ben Murdoch85b71792012-04-11 18:30:58 +01004191Literal* Parser::NewNumberLiteral(double number) {
4192 return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
4193}
4194
4195
Steve Blocka7e24c12009-10-30 11:49:00 +00004196Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01004197 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00004198 type, HandleVector<Object>(NULL, 0));
4199}
4200
4201
4202Expression* Parser::NewThrowSyntaxError(Handle<String> type,
4203 Handle<Object> first) {
4204 int argc = first.is_null() ? 0 : 1;
4205 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01004206 return NewThrowError(
4207 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004208}
4209
4210
4211Expression* Parser::NewThrowTypeError(Handle<String> type,
4212 Handle<Object> first,
4213 Handle<Object> second) {
4214 ASSERT(!first.is_null() && !second.is_null());
4215 Handle<Object> elements[] = { first, second };
4216 Vector< Handle<Object> > arguments =
4217 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01004218 return NewThrowError(
4219 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004220}
4221
4222
4223Expression* Parser::NewThrowError(Handle<String> constructor,
4224 Handle<String> type,
4225 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004226 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01004227 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
4228 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004229 for (int i = 0; i < argc; i++) {
4230 Handle<Object> element = arguments[i];
4231 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01004232 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00004233 }
4234 }
Ben Murdoch85b71792012-04-11 18:30:58 +01004235 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
4236 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01004237
Ben Murdoch257744e2011-11-30 15:57:28 +00004238 ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
Ben Murdoch85b71792012-04-11 18:30:58 +01004239 args->Add(NewLiteral(type));
4240 args->Add(NewLiteral(array));
4241 CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
4242 constructor,
4243 NULL,
4244 args);
4245 return new(zone()) Throw(isolate(),
4246 call_constructor,
4247 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00004248}
4249
Leon Clarke4515c472010-02-03 11:58:03 +00004250// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004251// Regular expressions
4252
4253
4254RegExpParser::RegExpParser(FlatStringReader* in,
4255 Handle<String>* error,
4256 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004257 : isolate_(Isolate::Current()),
4258 error_(error),
4259 captures_(NULL),
4260 in_(in),
4261 current_(kEndMarker),
4262 next_pos_(0),
4263 capture_count_(0),
4264 has_more_(true),
4265 multiline_(multiline),
4266 simple_(false),
4267 contains_anchor_(false),
4268 is_scanned_for_captures_(false),
4269 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004270 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004271}
4272
4273
4274uc32 RegExpParser::Next() {
4275 if (has_next()) {
4276 return in()->Get(next_pos_);
4277 } else {
4278 return kEndMarker;
4279 }
4280}
4281
4282
4283void RegExpParser::Advance() {
4284 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004285 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004286 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004287 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4288 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004289 ReportError(CStrVector("Regular expression too large"));
4290 } else {
4291 current_ = in()->Get(next_pos_);
4292 next_pos_++;
4293 }
4294 } else {
4295 current_ = kEndMarker;
4296 has_more_ = false;
4297 }
4298}
4299
4300
4301void RegExpParser::Reset(int pos) {
4302 next_pos_ = pos;
4303 Advance();
4304}
4305
4306
4307void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004308 next_pos_ += dist - 1;
4309 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004310}
4311
4312
4313bool RegExpParser::simple() {
4314 return simple_;
4315}
4316
4317RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4318 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004319 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004320 // Zip to the end to make sure the no more input is read.
4321 current_ = kEndMarker;
4322 next_pos_ = in()->length();
4323 return NULL;
4324}
4325
4326
4327// Pattern ::
4328// Disjunction
4329RegExpTree* RegExpParser::ParsePattern() {
4330 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4331 ASSERT(!has_more());
4332 // If the result of parsing is a literal string atom, and it has the
4333 // same length as the input, then the atom is identical to the input.
4334 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4335 simple_ = true;
4336 }
4337 return result;
4338}
4339
4340
4341// Disjunction ::
4342// Alternative
4343// Alternative | Disjunction
4344// Alternative ::
4345// [empty]
4346// Term Alternative
4347// Term ::
4348// Assertion
4349// Atom
4350// Atom Quantifier
4351RegExpTree* RegExpParser::ParseDisjunction() {
4352 // Used to store current state while parsing subexpressions.
4353 RegExpParserState initial_state(NULL, INITIAL, 0);
4354 RegExpParserState* stored_state = &initial_state;
4355 // Cache the builder in a local variable for quick access.
4356 RegExpBuilder* builder = initial_state.builder();
4357 while (true) {
4358 switch (current()) {
4359 case kEndMarker:
4360 if (stored_state->IsSubexpression()) {
4361 // Inside a parenthesized group when hitting end of input.
4362 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4363 }
4364 ASSERT_EQ(INITIAL, stored_state->group_type());
4365 // Parsing completed successfully.
4366 return builder->ToRegExp();
4367 case ')': {
4368 if (!stored_state->IsSubexpression()) {
4369 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4370 }
4371 ASSERT_NE(INITIAL, stored_state->group_type());
4372
4373 Advance();
4374 // End disjunction parsing and convert builder content to new single
4375 // regexp atom.
4376 RegExpTree* body = builder->ToRegExp();
4377
4378 int end_capture_index = captures_started();
4379
4380 int capture_index = stored_state->capture_index();
4381 SubexpressionType type = stored_state->group_type();
4382
4383 // Restore previous state.
4384 stored_state = stored_state->previous_state();
4385 builder = stored_state->builder();
4386
4387 // Build result of subexpression.
4388 if (type == CAPTURE) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01004389 RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004390 captures_->at(capture_index - 1) = capture;
4391 body = capture;
4392 } else if (type != GROUPING) {
4393 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4394 bool is_positive = (type == POSITIVE_LOOKAHEAD);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004395 body = new(zone()) RegExpLookahead(body,
Steve Blocka7e24c12009-10-30 11:49:00 +00004396 is_positive,
4397 end_capture_index - capture_index,
4398 capture_index);
4399 }
4400 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004401 // For compatability with JSC and ES3, we allow quantifiers after
4402 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004403 break;
4404 }
4405 case '|': {
4406 Advance();
4407 builder->NewAlternative();
4408 continue;
4409 }
4410 case '*':
4411 case '+':
4412 case '?':
4413 return ReportError(CStrVector("Nothing to repeat"));
4414 case '^': {
4415 Advance();
4416 if (multiline_) {
4417 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004418 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
Steve Blocka7e24c12009-10-30 11:49:00 +00004419 } else {
4420 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004421 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
Steve Blocka7e24c12009-10-30 11:49:00 +00004422 set_contains_anchor();
4423 }
4424 continue;
4425 }
4426 case '$': {
4427 Advance();
4428 RegExpAssertion::Type type =
4429 multiline_ ? RegExpAssertion::END_OF_LINE :
4430 RegExpAssertion::END_OF_INPUT;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004431 builder->AddAssertion(new(zone()) RegExpAssertion(type));
Steve Blocka7e24c12009-10-30 11:49:00 +00004432 continue;
4433 }
4434 case '.': {
4435 Advance();
4436 // everything except \x0a, \x0d, \u2028 and \u2029
Ben Murdoch257744e2011-11-30 15:57:28 +00004437 ZoneList<CharacterRange>* ranges =
4438 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004439 CharacterRange::AddClassEscape('.', ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004440 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004441 builder->AddAtom(atom);
4442 break;
4443 }
4444 case '(': {
4445 SubexpressionType type = CAPTURE;
4446 Advance();
4447 if (current() == '?') {
4448 switch (Next()) {
4449 case ':':
4450 type = GROUPING;
4451 break;
4452 case '=':
4453 type = POSITIVE_LOOKAHEAD;
4454 break;
4455 case '!':
4456 type = NEGATIVE_LOOKAHEAD;
4457 break;
4458 default:
4459 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4460 break;
4461 }
4462 Advance(2);
4463 } else {
4464 if (captures_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004465 captures_ = new(zone()) ZoneList<RegExpCapture*>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004466 }
4467 if (captures_started() >= kMaxCaptures) {
4468 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4469 }
4470 captures_->Add(NULL);
4471 }
4472 // Store current state and begin new disjunction parsing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004473 stored_state = new(zone()) RegExpParserState(stored_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00004474 type,
4475 captures_started());
4476 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004477 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004478 }
4479 case '[': {
4480 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4481 builder->AddAtom(atom);
4482 break;
4483 }
4484 // Atom ::
4485 // \ AtomEscape
4486 case '\\':
4487 switch (Next()) {
4488 case kEndMarker:
4489 return ReportError(CStrVector("\\ at end of pattern"));
4490 case 'b':
4491 Advance(2);
4492 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004493 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004494 continue;
4495 case 'B':
4496 Advance(2);
4497 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004498 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004499 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004500 // AtomEscape ::
4501 // CharacterClassEscape
4502 //
4503 // CharacterClassEscape :: one of
4504 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004505 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4506 uc32 c = Next();
4507 Advance(2);
Ben Murdoch257744e2011-11-30 15:57:28 +00004508 ZoneList<CharacterRange>* ranges =
4509 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004510 CharacterRange::AddClassEscape(c, ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004511 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004512 builder->AddAtom(atom);
4513 break;
4514 }
4515 case '1': case '2': case '3': case '4': case '5': case '6':
4516 case '7': case '8': case '9': {
4517 int index = 0;
4518 if (ParseBackReferenceIndex(&index)) {
4519 RegExpCapture* capture = NULL;
4520 if (captures_ != NULL && index <= captures_->length()) {
4521 capture = captures_->at(index - 1);
4522 }
4523 if (capture == NULL) {
4524 builder->AddEmpty();
4525 break;
4526 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004527 RegExpTree* atom = new(zone()) RegExpBackReference(capture);
Steve Blocka7e24c12009-10-30 11:49:00 +00004528 builder->AddAtom(atom);
4529 break;
4530 }
4531 uc32 first_digit = Next();
4532 if (first_digit == '8' || first_digit == '9') {
4533 // Treat as identity escape
4534 builder->AddCharacter(first_digit);
4535 Advance(2);
4536 break;
4537 }
4538 }
4539 // FALLTHROUGH
4540 case '0': {
4541 Advance();
4542 uc32 octal = ParseOctalLiteral();
4543 builder->AddCharacter(octal);
4544 break;
4545 }
4546 // ControlEscape :: one of
4547 // f n r t v
4548 case 'f':
4549 Advance(2);
4550 builder->AddCharacter('\f');
4551 break;
4552 case 'n':
4553 Advance(2);
4554 builder->AddCharacter('\n');
4555 break;
4556 case 'r':
4557 Advance(2);
4558 builder->AddCharacter('\r');
4559 break;
4560 case 't':
4561 Advance(2);
4562 builder->AddCharacter('\t');
4563 break;
4564 case 'v':
4565 Advance(2);
4566 builder->AddCharacter('\v');
4567 break;
4568 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004569 Advance();
4570 uc32 controlLetter = Next();
4571 // Special case if it is an ASCII letter.
4572 // Convert lower case letters to uppercase.
4573 uc32 letter = controlLetter & ~('a' ^ 'A');
4574 if (letter < 'A' || 'Z' < letter) {
4575 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4576 // This is outside the specification. We match JSC in
4577 // reading the backslash as a literal character instead
4578 // of as starting an escape.
4579 builder->AddCharacter('\\');
4580 } else {
4581 Advance(2);
4582 builder->AddCharacter(controlLetter & 0x1f);
4583 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004584 break;
4585 }
4586 case 'x': {
4587 Advance(2);
4588 uc32 value;
4589 if (ParseHexEscape(2, &value)) {
4590 builder->AddCharacter(value);
4591 } else {
4592 builder->AddCharacter('x');
4593 }
4594 break;
4595 }
4596 case 'u': {
4597 Advance(2);
4598 uc32 value;
4599 if (ParseHexEscape(4, &value)) {
4600 builder->AddCharacter(value);
4601 } else {
4602 builder->AddCharacter('u');
4603 }
4604 break;
4605 }
4606 default:
4607 // Identity escape.
4608 builder->AddCharacter(Next());
4609 Advance(2);
4610 break;
4611 }
4612 break;
4613 case '{': {
4614 int dummy;
4615 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4616 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4617 }
4618 // fallthrough
4619 }
4620 default:
4621 builder->AddCharacter(current());
4622 Advance();
4623 break;
4624 } // end switch(current())
4625
4626 int min;
4627 int max;
4628 switch (current()) {
4629 // QuantifierPrefix ::
4630 // *
4631 // +
4632 // ?
4633 // {
4634 case '*':
4635 min = 0;
4636 max = RegExpTree::kInfinity;
4637 Advance();
4638 break;
4639 case '+':
4640 min = 1;
4641 max = RegExpTree::kInfinity;
4642 Advance();
4643 break;
4644 case '?':
4645 min = 0;
4646 max = 1;
4647 Advance();
4648 break;
4649 case '{':
4650 if (ParseIntervalQuantifier(&min, &max)) {
4651 if (max < min) {
4652 ReportError(CStrVector("numbers out of order in {} quantifier.")
4653 CHECK_FAILED);
4654 }
4655 break;
4656 } else {
4657 continue;
4658 }
4659 default:
4660 continue;
4661 }
Leon Clarkee46be812010-01-19 14:06:41 +00004662 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004663 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004664 type = RegExpQuantifier::NON_GREEDY;
4665 Advance();
4666 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4667 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4668 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004669 Advance();
4670 }
Leon Clarkee46be812010-01-19 14:06:41 +00004671 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004672 }
4673}
4674
Steve Blocka7e24c12009-10-30 11:49:00 +00004675
4676#ifdef DEBUG
4677// Currently only used in an ASSERT.
4678static bool IsSpecialClassEscape(uc32 c) {
4679 switch (c) {
4680 case 'd': case 'D':
4681 case 's': case 'S':
4682 case 'w': case 'W':
4683 return true;
4684 default:
4685 return false;
4686 }
4687}
4688#endif
4689
4690
4691// In order to know whether an escape is a backreference or not we have to scan
4692// the entire regexp and find the number of capturing parentheses. However we
4693// don't want to scan the regexp twice unless it is necessary. This mini-parser
4694// is called when needed. It can see the difference between capturing and
4695// noncapturing parentheses and can skip character classes and backslash-escaped
4696// characters.
4697void RegExpParser::ScanForCaptures() {
4698 // Start with captures started previous to current position
4699 int capture_count = captures_started();
4700 // Add count of captures after this position.
4701 int n;
4702 while ((n = current()) != kEndMarker) {
4703 Advance();
4704 switch (n) {
4705 case '\\':
4706 Advance();
4707 break;
4708 case '[': {
4709 int c;
4710 while ((c = current()) != kEndMarker) {
4711 Advance();
4712 if (c == '\\') {
4713 Advance();
4714 } else {
4715 if (c == ']') break;
4716 }
4717 }
4718 break;
4719 }
4720 case '(':
4721 if (current() != '?') capture_count++;
4722 break;
4723 }
4724 }
4725 capture_count_ = capture_count;
4726 is_scanned_for_captures_ = true;
4727}
4728
4729
4730bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4731 ASSERT_EQ('\\', current());
4732 ASSERT('1' <= Next() && Next() <= '9');
4733 // Try to parse a decimal literal that is no greater than the total number
4734 // of left capturing parentheses in the input.
4735 int start = position();
4736 int value = Next() - '0';
4737 Advance(2);
4738 while (true) {
4739 uc32 c = current();
4740 if (IsDecimalDigit(c)) {
4741 value = 10 * value + (c - '0');
4742 if (value > kMaxCaptures) {
4743 Reset(start);
4744 return false;
4745 }
4746 Advance();
4747 } else {
4748 break;
4749 }
4750 }
4751 if (value > captures_started()) {
4752 if (!is_scanned_for_captures_) {
4753 int saved_position = position();
4754 ScanForCaptures();
4755 Reset(saved_position);
4756 }
4757 if (value > capture_count_) {
4758 Reset(start);
4759 return false;
4760 }
4761 }
4762 *index_out = value;
4763 return true;
4764}
4765
4766
4767// QuantifierPrefix ::
4768// { DecimalDigits }
4769// { DecimalDigits , }
4770// { DecimalDigits , DecimalDigits }
4771//
4772// Returns true if parsing succeeds, and set the min_out and max_out
4773// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4774bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4775 ASSERT_EQ(current(), '{');
4776 int start = position();
4777 Advance();
4778 int min = 0;
4779 if (!IsDecimalDigit(current())) {
4780 Reset(start);
4781 return false;
4782 }
4783 while (IsDecimalDigit(current())) {
4784 int next = current() - '0';
4785 if (min > (RegExpTree::kInfinity - next) / 10) {
4786 // Overflow. Skip past remaining decimal digits and return -1.
4787 do {
4788 Advance();
4789 } while (IsDecimalDigit(current()));
4790 min = RegExpTree::kInfinity;
4791 break;
4792 }
4793 min = 10 * min + next;
4794 Advance();
4795 }
4796 int max = 0;
4797 if (current() == '}') {
4798 max = min;
4799 Advance();
4800 } else if (current() == ',') {
4801 Advance();
4802 if (current() == '}') {
4803 max = RegExpTree::kInfinity;
4804 Advance();
4805 } else {
4806 while (IsDecimalDigit(current())) {
4807 int next = current() - '0';
4808 if (max > (RegExpTree::kInfinity - next) / 10) {
4809 do {
4810 Advance();
4811 } while (IsDecimalDigit(current()));
4812 max = RegExpTree::kInfinity;
4813 break;
4814 }
4815 max = 10 * max + next;
4816 Advance();
4817 }
4818 if (current() != '}') {
4819 Reset(start);
4820 return false;
4821 }
4822 Advance();
4823 }
4824 } else {
4825 Reset(start);
4826 return false;
4827 }
4828 *min_out = min;
4829 *max_out = max;
4830 return true;
4831}
4832
4833
Steve Blocka7e24c12009-10-30 11:49:00 +00004834uc32 RegExpParser::ParseOctalLiteral() {
4835 ASSERT('0' <= current() && current() <= '7');
4836 // For compatibility with some other browsers (not all), we parse
4837 // up to three octal digits with a value below 256.
4838 uc32 value = current() - '0';
4839 Advance();
4840 if ('0' <= current() && current() <= '7') {
4841 value = value * 8 + current() - '0';
4842 Advance();
4843 if (value < 32 && '0' <= current() && current() <= '7') {
4844 value = value * 8 + current() - '0';
4845 Advance();
4846 }
4847 }
4848 return value;
4849}
4850
4851
4852bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4853 int start = position();
4854 uc32 val = 0;
4855 bool done = false;
4856 for (int i = 0; !done; i++) {
4857 uc32 c = current();
4858 int d = HexValue(c);
4859 if (d < 0) {
4860 Reset(start);
4861 return false;
4862 }
4863 val = val * 16 + d;
4864 Advance();
4865 if (i == length - 1) {
4866 done = true;
4867 }
4868 }
4869 *value = val;
4870 return true;
4871}
4872
4873
4874uc32 RegExpParser::ParseClassCharacterEscape() {
4875 ASSERT(current() == '\\');
4876 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4877 Advance();
4878 switch (current()) {
4879 case 'b':
4880 Advance();
4881 return '\b';
4882 // ControlEscape :: one of
4883 // f n r t v
4884 case 'f':
4885 Advance();
4886 return '\f';
4887 case 'n':
4888 Advance();
4889 return '\n';
4890 case 'r':
4891 Advance();
4892 return '\r';
4893 case 't':
4894 Advance();
4895 return '\t';
4896 case 'v':
4897 Advance();
4898 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004899 case 'c': {
4900 uc32 controlLetter = Next();
4901 uc32 letter = controlLetter & ~('A' ^ 'a');
4902 // For compatibility with JSC, inside a character class
4903 // we also accept digits and underscore as control characters.
4904 if ((controlLetter >= '0' && controlLetter <= '9') ||
4905 controlLetter == '_' ||
4906 (letter >= 'A' && letter <= 'Z')) {
4907 Advance(2);
4908 // Control letters mapped to ASCII control characters in the range
4909 // 0x00-0x1f.
4910 return controlLetter & 0x1f;
4911 }
4912 // We match JSC in reading the backslash as a literal
4913 // character instead of as starting an escape.
4914 return '\\';
4915 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004916 case '0': case '1': case '2': case '3': case '4': case '5':
4917 case '6': case '7':
4918 // For compatibility, we interpret a decimal escape that isn't
4919 // a back reference (and therefore either \0 or not valid according
4920 // to the specification) as a 1..3 digit octal character code.
4921 return ParseOctalLiteral();
4922 case 'x': {
4923 Advance();
4924 uc32 value;
4925 if (ParseHexEscape(2, &value)) {
4926 return value;
4927 }
4928 // If \x is not followed by a two-digit hexadecimal, treat it
4929 // as an identity escape.
4930 return 'x';
4931 }
4932 case 'u': {
4933 Advance();
4934 uc32 value;
4935 if (ParseHexEscape(4, &value)) {
4936 return value;
4937 }
4938 // If \u is not followed by a four-digit hexadecimal, treat it
4939 // as an identity escape.
4940 return 'u';
4941 }
4942 default: {
4943 // Extended identity escape. We accept any character that hasn't
4944 // been matched by a more specific case, not just the subset required
4945 // by the ECMAScript specification.
4946 uc32 result = current();
4947 Advance();
4948 return result;
4949 }
4950 }
4951 return 0;
4952}
4953
4954
4955CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4956 ASSERT_EQ(0, *char_class);
4957 uc32 first = current();
4958 if (first == '\\') {
4959 switch (Next()) {
4960 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4961 *char_class = Next();
4962 Advance(2);
4963 return CharacterRange::Singleton(0); // Return dummy value.
4964 }
4965 case kEndMarker:
4966 return ReportError(CStrVector("\\ at end of pattern"));
4967 default:
4968 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4969 return CharacterRange::Singleton(c);
4970 }
4971 } else {
4972 Advance();
4973 return CharacterRange::Singleton(first);
4974 }
4975}
4976
4977
Ben Murdochb0fe1622011-05-05 13:52:32 +01004978static const uc16 kNoCharClass = 0;
4979
4980// Adds range or pre-defined character class to character ranges.
4981// If char_class is not kInvalidClass, it's interpreted as a class
4982// escape (i.e., 's' means whitespace, from '\s').
4983static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4984 uc16 char_class,
4985 CharacterRange range) {
4986 if (char_class != kNoCharClass) {
4987 CharacterRange::AddClassEscape(char_class, ranges);
4988 } else {
4989 ranges->Add(range);
4990 }
4991}
4992
4993
Steve Blocka7e24c12009-10-30 11:49:00 +00004994RegExpTree* RegExpParser::ParseCharacterClass() {
4995 static const char* kUnterminated = "Unterminated character class";
4996 static const char* kRangeOutOfOrder = "Range out of order in character class";
4997
4998 ASSERT_EQ(current(), '[');
4999 Advance();
5000 bool is_negated = false;
5001 if (current() == '^') {
5002 is_negated = true;
5003 Advance();
5004 }
Ben Murdoch257744e2011-11-30 15:57:28 +00005005 ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00005006 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005007 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00005008 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00005009 if (current() == '-') {
5010 Advance();
5011 if (current() == kEndMarker) {
5012 // If we reach the end we break out of the loop and let the
5013 // following code report an error.
5014 break;
5015 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005016 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005017 ranges->Add(CharacterRange::Singleton('-'));
5018 break;
5019 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01005020 uc16 char_class_2 = kNoCharClass;
5021 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
5022 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
5023 // Either end is an escaped character class. Treat the '-' verbatim.
5024 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005025 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01005026 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00005027 continue;
5028 }
5029 if (first.from() > next.to()) {
5030 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
5031 }
5032 ranges->Add(CharacterRange::Range(first.from(), next.to()));
5033 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005034 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005035 }
5036 }
5037 if (!has_more()) {
5038 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
5039 }
5040 Advance();
5041 if (ranges->length() == 0) {
5042 ranges->Add(CharacterRange::Everything());
5043 is_negated = !is_negated;
5044 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01005045 return new(zone()) RegExpCharacterClass(ranges, is_negated);
Steve Blocka7e24c12009-10-30 11:49:00 +00005046}
5047
5048
5049// ----------------------------------------------------------------------------
5050// The Parser interface.
5051
Steve Blocka7e24c12009-10-30 11:49:00 +00005052ParserMessage::~ParserMessage() {
5053 for (int i = 0; i < args().length(); i++)
5054 DeleteArray(args()[i]);
5055 DeleteArray(args().start());
5056}
5057
5058
5059ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01005060 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00005061}
5062
5063
5064int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01005065 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00005066}
5067
5068
Leon Clarkef7060e22010-06-03 12:02:55 +01005069const char* ScriptDataImpl::Data() {
5070 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00005071}
5072
5073
Leon Clarkee46be812010-01-19 14:06:41 +00005074bool ScriptDataImpl::HasError() {
5075 return has_error();
5076}
5077
5078
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005079void ScriptDataImpl::Initialize() {
5080 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005081 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5082 function_index_ = PreparseDataConstants::kHeaderSize;
5083 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5084 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005085 if (store_.length() > symbol_data_offset) {
5086 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5087 } else {
5088 // Partial preparse causes no symbol information.
5089 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5090 }
5091 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5092 }
5093}
5094
5095
5096int ScriptDataImpl::ReadNumber(byte** source) {
5097 // Reads a number from symbol_data_ in base 128. The most significant
5098 // bit marks that there are more digits.
5099 // If the first byte is 0x80 (kNumberTerminator), it would normally
5100 // represent a leading zero. Since that is useless, and therefore won't
5101 // appear as the first digit of any actual value, it is used to
5102 // mark the end of the input stream.
5103 byte* data = *source;
5104 if (data >= symbol_data_end_) return -1;
5105 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005106 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005107 // End of stream marker.
5108 return -1;
5109 }
5110 int result = input & 0x7f;
5111 data++;
5112 while ((input & 0x80u) != 0) {
5113 if (data >= symbol_data_end_) return -1;
5114 input = *data;
5115 result = (result << 7) | (input & 0x7f);
5116 data++;
5117 }
5118 *source = data;
5119 return result;
5120}
5121
5122
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005123// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdoch85b71792012-04-11 18:30:58 +01005124static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
5125 bool allow_lazy,
5126 ParserRecorder* recorder,
5127 bool harmony_block_scoping) {
Steve Block44f0eee2011-05-26 01:26:41 +01005128 Isolate* isolate = Isolate::Current();
Ben Murdoch85b71792012-04-11 18:30:58 +01005129 JavaScriptScanner scanner(isolate->unicode_cache());
5130 scanner.SetHarmonyBlockScoping(harmony_block_scoping);
Steve Block9fac8402011-05-12 15:51:54 +01005131 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01005132 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdoch85b71792012-04-11 18:30:58 +01005133 if (!preparser::PreParser::PreParseProgram(&scanner,
5134 recorder,
5135 allow_lazy,
5136 stack_limit)) {
Steve Block44f0eee2011-05-26 01:26:41 +01005137 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005138 return NULL;
5139 }
5140
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005141 // Extract the accumulated data from the recorder as a single
5142 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005143 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005144 return new ScriptDataImpl(store);
5145}
5146
5147
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005148// Preparse, but only collect data that is immediately useful,
5149// even if the preparser data is only used once.
Ben Murdoch85b71792012-04-11 18:30:58 +01005150ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005151 v8::Extension* extension,
Ben Murdoch85b71792012-04-11 18:30:58 +01005152 bool harmony_block_scoping) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005153 bool allow_lazy = FLAG_lazy && (extension == NULL);
5154 if (!allow_lazy) {
5155 // Partial preparsing is only about lazily compiled functions.
5156 // If we don't allow lazy compilation, the log data will be empty.
5157 return NULL;
5158 }
5159 PartialParserRecorder recorder;
Ben Murdoch85b71792012-04-11 18:30:58 +01005160 return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005161}
5162
5163
Ben Murdoch85b71792012-04-11 18:30:58 +01005164ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005165 v8::Extension* extension,
Ben Murdoch85b71792012-04-11 18:30:58 +01005166 bool harmony_block_scoping) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005167 Handle<Script> no_script;
Ben Murdoch85b71792012-04-11 18:30:58 +01005168 bool allow_lazy = FLAG_lazy && (extension == NULL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005169 CompleteParserRecorder recorder;
Ben Murdoch85b71792012-04-11 18:30:58 +01005170 return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005171}
5172
5173
5174bool RegExpParser::ParseRegExp(FlatStringReader* input,
5175 bool multiline,
5176 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005177 ASSERT(result != NULL);
5178 RegExpParser parser(input, &result->error, multiline);
5179 RegExpTree* tree = parser.ParsePattern();
5180 if (parser.failed()) {
5181 ASSERT(tree == NULL);
5182 ASSERT(!result->error.is_null());
5183 } else {
5184 ASSERT(tree != NULL);
5185 ASSERT(result->error.is_null());
5186 result->tree = tree;
5187 int capture_count = parser.captures_started();
5188 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5189 result->contains_anchor = parser.contains_anchor();
5190 result->capture_count = capture_count;
5191 }
5192 return !parser.failed();
5193}
5194
5195
Ben Murdoch85b71792012-04-11 18:30:58 +01005196bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005197 ASSERT(info->function() == NULL);
5198 FunctionLiteral* result = NULL;
5199 Handle<Script> script = info->script();
Ben Murdoch85b71792012-04-11 18:30:58 +01005200 bool harmony_block_scoping = !info->is_native() &&
5201 FLAG_harmony_block_scoping;
Ben Murdochf87a2032010-10-22 12:50:53 +01005202 if (info->is_lazy()) {
Ben Murdoch85b71792012-04-11 18:30:58 +01005203 bool allow_natives_syntax =
5204 FLAG_allow_natives_syntax ||
5205 info->is_native();
5206 Parser parser(script, allow_natives_syntax, NULL, NULL);
5207 parser.SetHarmonyBlockScoping(harmony_block_scoping);
5208 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00005209 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +01005210 // Whether we allow %identifier(..) syntax.
5211 bool allow_natives_syntax =
5212 info->is_native() || FLAG_allow_natives_syntax;
Ben Murdochf87a2032010-10-22 12:50:53 +01005213 ScriptDataImpl* pre_data = info->pre_parse_data();
Ben Murdoch85b71792012-04-11 18:30:58 +01005214 Parser parser(script,
5215 allow_natives_syntax,
5216 info->extension(),
5217 pre_data);
5218 parser.SetHarmonyBlockScoping(harmony_block_scoping);
Ben Murdochf87a2032010-10-22 12:50:53 +01005219 if (pre_data != NULL && pre_data->has_error()) {
5220 Scanner::Location loc = pre_data->MessageLocation();
5221 const char* message = pre_data->BuildMessage();
5222 Vector<const char*> args = pre_data->BuildArgs();
5223 parser.ReportMessageAt(loc, message, args);
5224 DeleteArray(message);
5225 for (int i = 0; i < args.length(); i++) {
5226 DeleteArray(args[i]);
5227 }
5228 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01005229 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01005230 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +01005231 Handle<String> source = Handle<String>(String::cast(script->source()));
5232 result = parser.ParseProgram(source,
5233 info->is_global(),
5234 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01005235 }
Leon Clarke4515c472010-02-03 11:58:03 +00005236 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005237 info->SetFunction(result);
5238 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005239}
5240
Steve Blocka7e24c12009-10-30 11:49:00 +00005241} } // namespace v8::internal