blob: 3c361a7e2e6760e4202258c659695c3ae1c8a82d [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "ast.h"
32#include "bootstrapper.h"
Steve Block6ded16b2010-05-10 14:33:55 +010033#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010035#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010036#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010037#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080039#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "runtime.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010041#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "string-stream.h"
43
Kristian Monsen25f61362010-05-21 11:50:48 +010044#include "ast-inl.h"
45#include "jump-target-inl.h"
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047namespace v8 {
48namespace internal {
49
Steve Blocka7e24c12009-10-30 11:49:00 +000050// PositionStack is used for on-stack allocation of token positions for
51// new expressions. Please look at ParseNewExpression.
52
53class PositionStack {
54 public:
55 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
56 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
57
58 class Element {
59 public:
60 Element(PositionStack* stack, int value) {
61 previous_ = stack->top();
62 value_ = value;
63 stack->set_top(this);
64 }
65
66 private:
67 Element* previous() { return previous_; }
68 int value() { return value_; }
69 friend class PositionStack;
70 Element* previous_;
71 int value_;
72 };
73
74 bool is_empty() { return top_ == NULL; }
75 int pop() {
76 ASSERT(!is_empty());
77 int result = top_->value();
78 top_ = top_->previous();
79 return result;
80 }
81
82 private:
83 Element* top() { return top_; }
84 void set_top(Element* value) { top_ = value; }
85 Element* top_;
86 bool* ok_;
87};
88
89
Steve Blocka7e24c12009-10-30 11:49:00 +000090RegExpBuilder::RegExpBuilder()
91 : pending_empty_(false),
92 characters_(NULL),
93 terms_(),
94 alternatives_()
95#ifdef DEBUG
96 , last_added_(ADD_NONE)
97#endif
98 {}
99
100
101void RegExpBuilder::FlushCharacters() {
102 pending_empty_ = false;
103 if (characters_ != NULL) {
104 RegExpTree* atom = new RegExpAtom(characters_->ToConstVector());
105 characters_ = NULL;
106 text_.Add(atom);
107 LAST(ADD_ATOM);
108 }
109}
110
111
112void RegExpBuilder::FlushText() {
113 FlushCharacters();
114 int num_text = text_.length();
115 if (num_text == 0) {
116 return;
117 } else if (num_text == 1) {
118 terms_.Add(text_.last());
119 } else {
120 RegExpText* text = new RegExpText();
121 for (int i = 0; i < num_text; i++)
122 text_.Get(i)->AppendToText(text);
123 terms_.Add(text);
124 }
125 text_.Clear();
126}
127
128
129void RegExpBuilder::AddCharacter(uc16 c) {
130 pending_empty_ = false;
131 if (characters_ == NULL) {
132 characters_ = new ZoneList<uc16>(4);
133 }
134 characters_->Add(c);
135 LAST(ADD_CHAR);
136}
137
138
139void RegExpBuilder::AddEmpty() {
140 pending_empty_ = true;
141}
142
143
144void RegExpBuilder::AddAtom(RegExpTree* term) {
145 if (term->IsEmpty()) {
146 AddEmpty();
147 return;
148 }
149 if (term->IsTextElement()) {
150 FlushCharacters();
151 text_.Add(term);
152 } else {
153 FlushText();
154 terms_.Add(term);
155 }
156 LAST(ADD_ATOM);
157}
158
159
160void RegExpBuilder::AddAssertion(RegExpTree* assert) {
161 FlushText();
162 terms_.Add(assert);
163 LAST(ADD_ASSERT);
164}
165
166
167void RegExpBuilder::NewAlternative() {
168 FlushTerms();
169}
170
171
172void RegExpBuilder::FlushTerms() {
173 FlushText();
174 int num_terms = terms_.length();
175 RegExpTree* alternative;
176 if (num_terms == 0) {
177 alternative = RegExpEmpty::GetInstance();
178 } else if (num_terms == 1) {
179 alternative = terms_.last();
180 } else {
181 alternative = new RegExpAlternative(terms_.GetList());
182 }
183 alternatives_.Add(alternative);
184 terms_.Clear();
185 LAST(ADD_NONE);
186}
187
188
189RegExpTree* RegExpBuilder::ToRegExp() {
190 FlushTerms();
191 int num_alternatives = alternatives_.length();
192 if (num_alternatives == 0) {
193 return RegExpEmpty::GetInstance();
194 }
195 if (num_alternatives == 1) {
196 return alternatives_.last();
197 }
198 return new RegExpDisjunction(alternatives_.GetList());
199}
200
201
Leon Clarkee46be812010-01-19 14:06:41 +0000202void RegExpBuilder::AddQuantifierToAtom(int min,
203 int max,
204 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (pending_empty_) {
206 pending_empty_ = false;
207 return;
208 }
209 RegExpTree* atom;
210 if (characters_ != NULL) {
211 ASSERT(last_added_ == ADD_CHAR);
212 // Last atom was character.
213 Vector<const uc16> char_vector = characters_->ToConstVector();
214 int num_chars = char_vector.length();
215 if (num_chars > 1) {
216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
217 text_.Add(new RegExpAtom(prefix));
218 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219 }
220 characters_ = NULL;
221 atom = new RegExpAtom(char_vector);
222 FlushText();
223 } else if (text_.length() > 0) {
224 ASSERT(last_added_ == ADD_ATOM);
225 atom = text_.RemoveLast();
226 FlushText();
227 } else if (terms_.length() > 0) {
228 ASSERT(last_added_ == ADD_ATOM);
229 atom = terms_.RemoveLast();
230 if (atom->max_match() == 0) {
231 // Guaranteed to only match an empty string.
232 LAST(ADD_TERM);
233 if (min == 0) {
234 return;
235 }
236 terms_.Add(atom);
237 return;
238 }
239 } else {
240 // Only call immediately after adding an atom or character!
241 UNREACHABLE();
242 return;
243 }
Leon Clarkee46be812010-01-19 14:06:41 +0000244 terms_.Add(new RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 LAST(ADD_TERM);
246}
247
248
Steve Blocka7e24c12009-10-30 11:49:00 +0000249// A temporary scope stores information during parsing, just like
250// a plain scope. However, temporary scopes are not kept around
251// after parsing or referenced by syntax trees so they can be stack-
252// allocated and hence used by the pre-parser.
253class TemporaryScope BASE_EMBEDDED {
254 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800255 explicit TemporaryScope(TemporaryScope** variable);
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 ~TemporaryScope();
257
258 int NextMaterializedLiteralIndex() {
259 int next_index =
260 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
261 materialized_literal_count_++;
262 return next_index;
263 }
264 int materialized_literal_count() { return materialized_literal_count_; }
265
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 void SetThisPropertyAssignmentInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000267 bool only_simple_this_property_assignments,
268 Handle<FixedArray> this_property_assignments) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000269 only_simple_this_property_assignments_ =
270 only_simple_this_property_assignments;
271 this_property_assignments_ = this_property_assignments;
272 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 bool only_simple_this_property_assignments() {
274 return only_simple_this_property_assignments_;
275 }
276 Handle<FixedArray> this_property_assignments() {
277 return this_property_assignments_;
278 }
279
280 void AddProperty() { expected_property_count_++; }
281 int expected_property_count() { return expected_property_count_; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100282
283 void AddLoop() { loop_count_++; }
284 bool ContainsLoops() const { return loop_count_ > 0; }
285
Steve Block1e0659c2011-05-24 12:43:12 +0100286 bool StrictMode() { return strict_mode_; }
287 void EnableStrictMode() {
288 strict_mode_ = FLAG_strict_mode;
289 }
290
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 private:
Steve Block3ce2e202009-11-05 08:53:23 +0000292 // Captures the number of literals that need materialization in the
293 // function. Includes regexp literals, and boilerplate for object
294 // and array literals.
Steve Blocka7e24c12009-10-30 11:49:00 +0000295 int materialized_literal_count_;
296
Steve Blocka7e24c12009-10-30 11:49:00 +0000297 // Properties count estimation.
298 int expected_property_count_;
299
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100300 // Keeps track of assignments to properties of this. Used for
301 // optimizing constructors.
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 bool only_simple_this_property_assignments_;
303 Handle<FixedArray> this_property_assignments_;
304
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100305 // Captures the number of loops inside the scope.
306 int loop_count_;
307
Steve Block1e0659c2011-05-24 12:43:12 +0100308 // Parsing strict mode code.
309 bool strict_mode_;
310
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 // Bookkeeping
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800312 TemporaryScope** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 TemporaryScope* parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000314};
315
316
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800317TemporaryScope::TemporaryScope(TemporaryScope** variable)
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 : materialized_literal_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 expected_property_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000320 only_simple_this_property_assignments_(false),
321 this_property_assignments_(Factory::empty_fixed_array()),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100322 loop_count_(0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800323 variable_(variable),
324 parent_(*variable) {
Steve Block1e0659c2011-05-24 12:43:12 +0100325 // Inherit the strict mode from the parent scope.
326 strict_mode_ = (parent_ != NULL) && parent_->strict_mode_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800327 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000328}
329
330
331TemporaryScope::~TemporaryScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800332 *variable_ = parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000333}
334
335
Steve Block9fac8402011-05-12 15:51:54 +0100336Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800337 // Length of symbol cache is the number of identified symbols.
338 // If we are larger than that, or negative, it's not a cached symbol.
339 // This might also happen if there is no preparser symbol data, even
340 // if there is some preparser data.
341 if (static_cast<unsigned>(symbol_id)
342 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100343 if (scanner().is_literal_ascii()) {
344 return Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
345 } else {
346 return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
347 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800348 }
Steve Block9fac8402011-05-12 15:51:54 +0100349 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800350}
351
352
Steve Block9fac8402011-05-12 15:51:54 +0100353Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800354 // Make sure the cache is large enough to hold the symbol identifier.
355 if (symbol_cache_.length() <= symbol_id) {
356 // Increase length to index + 1.
357 symbol_cache_.AddBlock(Handle<String>::null(),
358 symbol_id + 1 - symbol_cache_.length());
359 }
360 Handle<String> result = symbol_cache_.at(symbol_id);
361 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100362 if (scanner().is_literal_ascii()) {
363 result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
364 } else {
365 result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
366 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800367 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100368 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800370 Counters::total_preparse_symbols_skipped.Increment();
371 return result;
372}
Steve Blocka7e24c12009-10-30 11:49:00 +0000373
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800374
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100375FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
376 // The current pre-data entry must be a FunctionEntry with the given
377 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100378 if ((function_index_ + FunctionEntry::kSize <= store_.length())
379 && (static_cast<int>(store_[function_index_]) == start)) {
380 int index = function_index_;
381 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100382 return FunctionEntry(store_.SubVector(index,
383 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 }
385 return FunctionEntry();
386}
387
388
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100389int ScriptDataImpl::GetSymbolIdentifier() {
390 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100391}
392
393
Iain Merrick9ac36c92010-09-13 15:29:50 +0100394bool ScriptDataImpl::SanityCheck() {
395 // Check that the header data is valid and doesn't specify
396 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800397 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
398 if (magic() != PreparseDataConstants::kMagicNumber) return false;
399 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100400 if (has_error()) {
401 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800402 if (store_.length() <= PreparseDataConstants::kHeaderSize
403 + PreparseDataConstants::kMessageTextPos) {
404 return false;
405 }
406 if (Read(PreparseDataConstants::kMessageStartPos) >
407 Read(PreparseDataConstants::kMessageEndPos)) {
408 return false;
409 }
410 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
411 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100412 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800413 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
414 return false;
415 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100416 int length = static_cast<int>(Read(pos));
417 if (length < 0) return false;
418 pos += 1 + length;
419 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800420 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
421 return false;
422 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100423 return true;
424 }
425 // Check that the space allocated for function entries is sane.
426 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800427 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100428 if (functions_size < 0) return false;
429 if (functions_size % FunctionEntry::kSize != 0) return false;
430 // Check that the count of symbols is non-negative.
431 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800432 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100433 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100434 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100435 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800436 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100437 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 return true;
439}
440
441
Steve Block59151502010-09-22 15:07:15 +0100442
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100443const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 int length = start[0];
445 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100446 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100448 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 result[length] = '\0';
450 if (chars != NULL) *chars = length;
451 return result;
452}
453
Steve Blocka7e24c12009-10-30 11:49:00 +0000454Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800455 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
456 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 return Scanner::Location(beg_pos, end_pos);
458}
459
460
461const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800462 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100463 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000464}
465
466
467Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800468 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100470 // Position after text found by skipping past length field and
471 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800472 int pos = PreparseDataConstants::kMessageTextPos + 1
473 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 for (int i = 0; i < arg_count; i++) {
475 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100476 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000477 pos += count + 1;
478 }
479 return Vector<const char*>(array, arg_count);
480}
481
482
483unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800484 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000485}
486
487
488unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800489 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000490}
491
492
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800493Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 Scope* result = new Scope(parent, type);
495 result->Initialize(inside_with);
496 return result;
497}
498
Steve Blocka7e24c12009-10-30 11:49:00 +0000499// ----------------------------------------------------------------------------
500// Target is a support class to facilitate manipulation of the
501// Parser's target_stack_ (the stack of potential 'break' and
502// 'continue' statement targets). Upon construction, a new target is
503// added; it is removed upon destruction.
504
505class Target BASE_EMBEDDED {
506 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800507 Target(Target** variable, AstNode* node)
508 : variable_(variable), node_(node), previous_(*variable) {
509 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 }
511
512 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800513 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000514 }
515
516 Target* previous() { return previous_; }
517 AstNode* node() { return node_; }
518
519 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800520 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 AstNode* node_;
522 Target* previous_;
523};
524
525
526class TargetScope BASE_EMBEDDED {
527 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800528 explicit TargetScope(Target** variable)
529 : variable_(variable), previous_(*variable) {
530 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000531 }
532
533 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800534 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 }
536
537 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800538 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 Target* previous_;
540};
541
542
543// ----------------------------------------------------------------------------
544// LexicalScope is a support class to facilitate manipulation of the
545// Parser's scope stack. The constructor sets the parser's top scope
546// to the incoming scope, and the destructor resets it.
547
548class LexicalScope BASE_EMBEDDED {
549 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800550 LexicalScope(Scope** scope_variable,
551 int* with_nesting_level_variable,
552 Scope* scope)
553 : scope_variable_(scope_variable),
554 with_nesting_level_variable_(with_nesting_level_variable),
555 prev_scope_(*scope_variable),
556 prev_level_(*with_nesting_level_variable) {
557 *scope_variable = scope;
558 *with_nesting_level_variable = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000559 }
560
561 ~LexicalScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800562 (*scope_variable_)->Leave();
563 *scope_variable_ = prev_scope_;
564 *with_nesting_level_variable_ = prev_level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 }
566
567 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800568 Scope** scope_variable_;
569 int* with_nesting_level_variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000570 Scope* prev_scope_;
571 int prev_level_;
572};
573
Steve Blocka7e24c12009-10-30 11:49:00 +0000574// ----------------------------------------------------------------------------
575// The CHECK_OK macro is a convenient macro to enforce error
576// handling for functions that may fail (by returning !*ok).
577//
578// CAUTION: This macro appends extra statements after a call,
579// thus it must never be used where only a single statement
580// is correct (e.g. an if statement branch w/o braces)!
581
582#define CHECK_OK ok); \
583 if (!*ok) return NULL; \
584 ((void)0
585#define DUMMY ) // to make indentation work
586#undef DUMMY
587
588#define CHECK_FAILED /**/); \
589 if (failed_) return NULL; \
590 ((void)0
591#define DUMMY ) // to make indentation work
592#undef DUMMY
593
594// ----------------------------------------------------------------------------
595// Implementation of Parser
596
597Parser::Parser(Handle<Script> script,
598 bool allow_natives_syntax,
599 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000600 ScriptDataImpl* pre_data)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800601 : symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
602 script_(script),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100603 scanner_(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000604 top_scope_(NULL),
605 with_nesting_level_(0),
606 temp_scope_(NULL),
607 target_stack_(NULL),
608 allow_natives_syntax_(allow_natives_syntax),
609 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100610 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100611 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100612 stack_overflow_(false),
613 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100614 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000615}
616
617
Steve Blocka7e24c12009-10-30 11:49:00 +0000618FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Block1e0659c2011-05-24 12:43:12 +0100619 bool in_global_context,
620 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000621 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
622
623 HistogramTimerScope timer(&Counters::parse);
624 Counters::total_parse_size.Increment(source->length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100625 fni_ = new FuncNameInferrer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000626
627 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100628 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100629 if (source->IsExternalTwoByteString()) {
630 // Notice that the stream is destroyed at the end of the branch block.
631 // The last line of the blocks can't be moved outside, even though they're
632 // identical calls.
633 ExternalTwoByteStringUC16CharacterStream stream(
634 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100635 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100636 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100637 } else {
638 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100639 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100640 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100641 }
642}
643
644
645FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
646 bool in_global_context,
Steve Block1e0659c2011-05-24 12:43:12 +0100647 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100650 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000651
652 // Compute the parsing mode.
653 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
654 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
655
656 Scope::Type type =
657 in_global_context
658 ? Scope::GLOBAL_SCOPE
659 : Scope::EVAL_SCOPE;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800660 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000661
662 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800663 { Scope* scope = NewScope(top_scope_, type, inside_with());
664 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
665 scope);
666 TemporaryScope temp_scope(&this->temp_scope_);
Steve Block1e0659c2011-05-24 12:43:12 +0100667 if (strict_mode == kStrictMode) {
668 temp_scope.EnableStrictMode();
669 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800670 ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000671 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100672 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800673 ParseSourceElements(body, Token::EOS, &ok);
Steve Block1e0659c2011-05-24 12:43:12 +0100674 if (ok && temp_scope_->StrictMode()) {
675 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
676 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000677 if (ok) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800678 result = new FunctionLiteral(
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 no_name,
680 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800681 body,
Steve Blocka7e24c12009-10-30 11:49:00 +0000682 temp_scope.materialized_literal_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 temp_scope.expected_property_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000684 temp_scope.only_simple_this_property_assignments(),
685 temp_scope.this_property_assignments(),
686 0,
687 0,
688 source->length(),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100689 false,
Steve Block1e0659c2011-05-24 12:43:12 +0100690 temp_scope.ContainsLoops(),
691 temp_scope.StrictMode());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100692 } else if (stack_overflow_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000693 Top::StackOverflow();
694 }
695 }
696
697 // Make sure the target stack is empty.
698 ASSERT(target_stack_ == NULL);
699
700 // If there was a syntax error we have to get rid of the AST
701 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100702 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000703 return result;
704}
705
Ben Murdochf87a2032010-10-22 12:50:53 +0100706FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000707 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
708 HistogramTimerScope timer(&Counters::parse_lazy);
Ben Murdochf87a2032010-10-22 12:50:53 +0100709 Handle<String> source(String::cast(script_->source()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000710 Counters::total_parse_size.Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000711
Ben Murdochb0fe1622011-05-05 13:52:32 +0100712 // Initialize parser state.
713 source->TryFlatten();
714 if (source->IsExternalTwoByteString()) {
715 ExternalTwoByteStringUC16CharacterStream stream(
716 Handle<ExternalTwoByteString>::cast(source),
717 info->start_position(),
718 info->end_position());
719 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
720 return result;
721 } else {
722 GenericStringUC16CharacterStream stream(source,
723 info->start_position(),
724 info->end_position());
725 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
726 return result;
727 }
728}
729
730
731FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
732 UC16CharacterStream* source,
733 ZoneScope* zone_scope) {
Steve Block9fac8402011-05-12 15:51:54 +0100734 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100735 ASSERT(target_stack_ == NULL);
736
Ben Murdochf87a2032010-10-22 12:50:53 +0100737 Handle<String> name(String::cast(info->name()));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100738 fni_ = new FuncNameInferrer();
739 fni_->PushEnclosingName(name);
740
Steve Blocka7e24c12009-10-30 11:49:00 +0000741 mode_ = PARSE_EAGERLY;
742
743 // Place holder for the result.
744 FunctionLiteral* result = NULL;
745
746 {
747 // Parse the function literal.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800748 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000749 Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800750 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
751 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
752 scope);
753 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000754
Steve Block1e0659c2011-05-24 12:43:12 +0100755 if (info->strict_mode()) {
756 temp_scope.EnableStrictMode();
757 }
758
Ben Murdochf87a2032010-10-22 12:50:53 +0100759 FunctionLiteralType type =
760 info->is_expression() ? EXPRESSION : DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000761 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100762 result = ParseFunctionLiteral(name,
763 false, // Strict mode name already checked.
764 RelocInfo::kNoPosition, type, &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000765 // Make sure the results agree.
766 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000767 }
768
769 // Make sure the target stack is empty.
770 ASSERT(target_stack_ == NULL);
771
772 // If there was a stack overflow we have to get rid of AST and it is
773 // not safe to do before scope has been deleted.
774 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100775 zone_scope->DeleteOnExit();
Steve Block1e0659c2011-05-24 12:43:12 +0100776 if (stack_overflow_) Top::StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100777 } else {
778 Handle<String> inferred_name(info->inferred_name());
779 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 }
781 return result;
782}
783
Ben Murdochf87a2032010-10-22 12:50:53 +0100784
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800785Handle<String> Parser::GetSymbol(bool* ok) {
786 int symbol_id = -1;
787 if (pre_data() != NULL) {
788 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000789 }
Steve Block9fac8402011-05-12 15:51:54 +0100790 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000791}
Steve Blocka7e24c12009-10-30 11:49:00 +0000792
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800793
Steve Blocka7e24c12009-10-30 11:49:00 +0000794void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100795 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000796 ReportMessageAt(source_location, type, args);
797}
798
799
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800800void Parser::ReportMessageAt(Scanner::Location source_location,
801 const char* type,
802 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000803 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100804 source_location.beg_pos,
805 source_location.end_pos);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100806 Handle<FixedArray> elements = Factory::NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000807 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100808 Handle<String> arg_string = Factory::NewStringFromUtf8(CStrVector(args[i]));
809 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000810 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100811 Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
Steve Blocka7e24c12009-10-30 11:49:00 +0000812 Handle<Object> result = Factory::NewSyntaxError(type, array);
813 Top::Throw(*result, &location);
814}
815
816
Ben Murdochb8e0da22011-05-16 14:20:40 +0100817void Parser::ReportMessageAt(Scanner::Location source_location,
818 const char* type,
819 Vector<Handle<String> > args) {
820 MessageLocation location(script_,
821 source_location.beg_pos,
822 source_location.end_pos);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100823 Handle<FixedArray> elements = Factory::NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100824 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100825 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100826 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100827 Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100828 Handle<Object> result = Factory::NewSyntaxError(type, array);
829 Top::Throw(*result, &location);
830}
831
832
Steve Blocka7e24c12009-10-30 11:49:00 +0000833// Base class containing common code for the different finder classes used by
834// the parser.
835class ParserFinder {
836 protected:
837 ParserFinder() {}
838 static Assignment* AsAssignment(Statement* stat) {
839 if (stat == NULL) return NULL;
840 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
841 if (exp_stat == NULL) return NULL;
842 return exp_stat->expression()->AsAssignment();
843 }
844};
845
846
847// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000848// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000849class InitializationBlockFinder : public ParserFinder {
850 public:
851 InitializationBlockFinder()
852 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
853
854 ~InitializationBlockFinder() {
855 if (InBlock()) EndBlock();
856 }
857
858 void Update(Statement* stat) {
859 Assignment* assignment = AsAssignment(stat);
860 if (InBlock()) {
861 if (BlockContinues(assignment)) {
862 UpdateBlock(assignment);
863 } else {
864 EndBlock();
865 }
866 }
867 if (!InBlock() && (assignment != NULL) &&
868 (assignment->op() == Token::ASSIGN)) {
869 StartBlock(assignment);
870 }
871 }
872
873 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800874 // The minimum number of contiguous assignment that will
875 // be treated as an initialization block. Benchmarks show that
876 // the overhead exceeds the savings below this limit.
877 static const int kMinInitializationBlock = 3;
878
Steve Blocka7e24c12009-10-30 11:49:00 +0000879 // Returns true if the expressions appear to denote the same object.
880 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000881 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000882 static bool SameObject(Expression* e1, Expression* e2) {
883 VariableProxy* v1 = e1->AsVariableProxy();
884 VariableProxy* v2 = e2->AsVariableProxy();
885 if (v1 != NULL && v2 != NULL) {
886 return v1->name()->Equals(*v2->name());
887 }
888 Property* p1 = e1->AsProperty();
889 Property* p2 = e2->AsProperty();
890 if ((p1 == NULL) || (p2 == NULL)) return false;
891 Literal* key1 = p1->key()->AsLiteral();
892 Literal* key2 = p2->key()->AsLiteral();
893 if ((key1 == NULL) || (key2 == NULL)) return false;
894 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
895 return false;
896 }
897 String* name1 = String::cast(*key1->handle());
898 String* name2 = String::cast(*key2->handle());
899 if (!name1->Equals(name2)) return false;
900 return SameObject(p1->obj(), p2->obj());
901 }
902
903 // Returns true if the expressions appear to denote different properties
904 // of the same object.
905 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
906 Property* p1 = e1->AsProperty();
907 Property* p2 = e2->AsProperty();
908 if ((p1 == NULL) || (p2 == NULL)) return false;
909 return SameObject(p1->obj(), p2->obj());
910 }
911
912 bool BlockContinues(Assignment* assignment) {
913 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
914 if (assignment->op() != Token::ASSIGN) return false;
915 return PropertyOfSameObject(first_in_block_->target(),
916 assignment->target());
917 }
918
919 void StartBlock(Assignment* assignment) {
920 first_in_block_ = assignment;
921 last_in_block_ = assignment;
922 block_size_ = 1;
923 }
924
925 void UpdateBlock(Assignment* assignment) {
926 last_in_block_ = assignment;
927 ++block_size_;
928 }
929
930 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800931 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 first_in_block_->mark_block_start();
933 last_in_block_->mark_block_end();
934 }
935 last_in_block_ = first_in_block_ = NULL;
936 block_size_ = 0;
937 }
938
939 bool InBlock() { return first_in_block_ != NULL; }
940
941 Assignment* first_in_block_;
942 Assignment* last_in_block_;
943 int block_size_;
944
945 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
946};
947
948
949// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
950// this.x = ...;, where x is a named property. It also determines whether a
951// function contains only assignments of this type.
952class ThisNamedPropertyAssigmentFinder : public ParserFinder {
953 public:
954 ThisNamedPropertyAssigmentFinder()
Steve Blockd0582a62009-12-15 09:54:21 +0000955 : only_simple_this_property_assignments_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000956 names_(NULL),
957 assigned_arguments_(NULL),
958 assigned_constants_(NULL) {}
959
960 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000961 // Bail out if function already has property assignment that are
962 // not simple this property assignments.
963 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000964 return;
965 }
966
967 // Check whether this statement is of the form this.x = ...;
968 Assignment* assignment = AsAssignment(stat);
969 if (IsThisPropertyAssignment(assignment)) {
970 HandleThisPropertyAssignment(scope, assignment);
971 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000972 only_simple_this_property_assignments_ = false;
973 }
974 }
975
Steve Blocka7e24c12009-10-30 11:49:00 +0000976 // Returns whether only statements of the form this.x = y; where y is either a
977 // constant or a function argument was encountered.
978 bool only_simple_this_property_assignments() {
979 return only_simple_this_property_assignments_;
980 }
981
982 // Returns a fixed array containing three elements for each assignment of the
983 // form this.x = y;
984 Handle<FixedArray> GetThisPropertyAssignments() {
985 if (names_ == NULL) {
986 return Factory::empty_fixed_array();
987 }
988 ASSERT(names_ != NULL);
989 ASSERT(assigned_arguments_ != NULL);
990 ASSERT_EQ(names_->length(), assigned_arguments_->length());
991 ASSERT_EQ(names_->length(), assigned_constants_->length());
992 Handle<FixedArray> assignments =
993 Factory::NewFixedArray(names_->length() * 3);
994 for (int i = 0; i < names_->length(); i++) {
995 assignments->set(i * 3, *names_->at(i));
996 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
997 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
998 }
999 return assignments;
1000 }
1001
1002 private:
1003 bool IsThisPropertyAssignment(Assignment* assignment) {
1004 if (assignment != NULL) {
1005 Property* property = assignment->target()->AsProperty();
1006 return assignment->op() == Token::ASSIGN
1007 && property != NULL
1008 && property->obj()->AsVariableProxy() != NULL
1009 && property->obj()->AsVariableProxy()->is_this();
1010 }
1011 return false;
1012 }
1013
1014 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +01001015 // Check that the property assigned to is a named property, which is not
1016 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +00001017 Property* property = assignment->target()->AsProperty();
1018 ASSERT(property != NULL);
1019 Literal* literal = property->key()->AsLiteral();
1020 uint32_t dummy;
1021 if (literal != NULL &&
1022 literal->handle()->IsString() &&
Steve Block6ded16b2010-05-10 14:33:55 +01001023 !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001024 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1025 Handle<String> key = Handle<String>::cast(literal->handle());
1026
1027 // Check whether the value assigned is either a constant or matches the
1028 // name of one of the arguments to the function.
1029 if (assignment->value()->AsLiteral() != NULL) {
1030 // Constant assigned.
1031 Literal* literal = assignment->value()->AsLiteral();
1032 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001033 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001034 } else if (assignment->value()->AsVariableProxy() != NULL) {
1035 // Variable assigned.
1036 Handle<String> name =
1037 assignment->value()->AsVariableProxy()->name();
1038 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001039 for (int i = 0; i < scope->num_parameters(); i++) {
1040 if (*scope->parameter(i)->name() == *name) {
1041 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001042 AssignmentFromParameter(key, i);
1043 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001044 }
1045 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 }
1047 }
Steve Blockd0582a62009-12-15 09:54:21 +00001048 // It is not a simple "this.x = value;" assignment with a constant
1049 // or parameter value.
1050 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001051 }
1052
1053 void AssignmentFromParameter(Handle<String> name, int index) {
1054 EnsureAllocation();
1055 names_->Add(name);
1056 assigned_arguments_->Add(index);
1057 assigned_constants_->Add(Factory::undefined_value());
1058 }
1059
1060 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
1061 EnsureAllocation();
1062 names_->Add(name);
1063 assigned_arguments_->Add(-1);
1064 assigned_constants_->Add(value);
1065 }
1066
Steve Blockd0582a62009-12-15 09:54:21 +00001067 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001068 // The this assignment is not a simple one.
1069 only_simple_this_property_assignments_ = false;
1070 }
1071
1072 void EnsureAllocation() {
1073 if (names_ == NULL) {
1074 ASSERT(assigned_arguments_ == NULL);
1075 ASSERT(assigned_constants_ == NULL);
1076 names_ = new ZoneStringList(4);
1077 assigned_arguments_ = new ZoneList<int>(4);
1078 assigned_constants_ = new ZoneObjectList(4);
1079 }
1080 }
1081
Steve Blocka7e24c12009-10-30 11:49:00 +00001082 bool only_simple_this_property_assignments_;
1083 ZoneStringList* names_;
1084 ZoneList<int>* assigned_arguments_;
1085 ZoneObjectList* assigned_constants_;
1086};
1087
1088
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001089void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001090 int end_token,
1091 bool* ok) {
1092 // SourceElements ::
1093 // (Statement)* <end_token>
1094
1095 // Allocate a target stack to use for this set of source
1096 // elements. This way, all scripts and functions get their own
1097 // target stack thus avoiding illegal breaks and continues across
1098 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001099 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001100
1101 ASSERT(processor != NULL);
1102 InitializationBlockFinder block_finder;
1103 ThisNamedPropertyAssigmentFinder this_property_assignment_finder;
Steve Block1e0659c2011-05-24 12:43:12 +01001104 bool directive_prologue = true; // Parsing directive prologue.
1105
Steve Blocka7e24c12009-10-30 11:49:00 +00001106 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001107 if (directive_prologue && peek() != Token::STRING) {
1108 directive_prologue = false;
1109 }
1110
1111 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001112
1113 Statement* stat;
1114 if (peek() == Token::FUNCTION) {
1115 // FunctionDeclaration is only allowed in the context of SourceElements
1116 // (Ecma 262 5th Edition, clause 14):
1117 // SourceElement:
1118 // Statement
1119 // FunctionDeclaration
1120 // Common language extension is to allow function declaration in place
1121 // of any statement. This language extension is disabled in strict mode.
1122 stat = ParseFunctionDeclaration(CHECK_OK);
1123 } else {
1124 stat = ParseStatement(NULL, CHECK_OK);
1125 }
Steve Block1e0659c2011-05-24 12:43:12 +01001126
1127 if (stat == NULL || stat->IsEmpty()) {
1128 directive_prologue = false; // End of directive prologue.
1129 continue;
1130 }
1131
1132 if (directive_prologue) {
1133 // A shot at a directive.
1134 ExpressionStatement *e_stat;
1135 Literal *literal;
1136 // Still processing directive prologue?
1137 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1138 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1139 literal->handle()->IsString()) {
1140 Handle<String> directive = Handle<String>::cast(literal->handle());
1141
1142 // Check "use strict" directive (ES5 14.1).
1143 if (!temp_scope_->StrictMode() &&
1144 directive->Equals(Heap::use_strict()) &&
1145 token_loc.end_pos - token_loc.beg_pos ==
1146 Heap::use_strict()->length() + 2) {
1147 temp_scope_->EnableStrictMode();
1148 // "use strict" is the only directive for now.
1149 directive_prologue = false;
1150 }
1151 } else {
1152 // End of the directive prologue.
1153 directive_prologue = false;
1154 }
1155 }
1156
Steve Blocka7e24c12009-10-30 11:49:00 +00001157 // We find and mark the initialization blocks on top level code only.
1158 // This is because the optimization prevents reuse of the map transitions,
1159 // so it should be used only for code that will only be run once.
1160 if (top_scope_->is_global_scope()) {
1161 block_finder.Update(stat);
1162 }
1163 // Find and mark all assignments to named properties in this (this.x =)
1164 if (top_scope_->is_function_scope()) {
1165 this_property_assignment_finder.Update(top_scope_, stat);
1166 }
1167 processor->Add(stat);
1168 }
1169
1170 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001171 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001172 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001173 this_property_assignment_finder.only_simple_this_property_assignments()
1174 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001175 if (only_simple_this_property_assignments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 temp_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001177 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001178 this_property_assignment_finder.GetThisPropertyAssignments());
1179 }
1180 }
1181 return 0;
1182}
1183
1184
1185Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1186 // Statement ::
1187 // Block
1188 // VariableStatement
1189 // EmptyStatement
1190 // ExpressionStatement
1191 // IfStatement
1192 // IterationStatement
1193 // ContinueStatement
1194 // BreakStatement
1195 // ReturnStatement
1196 // WithStatement
1197 // LabelledStatement
1198 // SwitchStatement
1199 // ThrowStatement
1200 // TryStatement
1201 // DebuggerStatement
1202
1203 // Note: Since labels can only be used by 'break' and 'continue'
1204 // statements, which themselves are only valid within blocks,
1205 // iterations or 'switch' statements (i.e., BreakableStatements),
1206 // labels can be simply ignored in all other cases; except for
1207 // trivial labeled break statements 'label: break label' which is
1208 // parsed into an empty statement.
1209
1210 // Keep the source position of the statement
1211 int statement_pos = scanner().peek_location().beg_pos;
1212 Statement* stmt = NULL;
1213 switch (peek()) {
1214 case Token::LBRACE:
1215 return ParseBlock(labels, ok);
1216
1217 case Token::CONST: // fall through
1218 case Token::VAR:
1219 stmt = ParseVariableStatement(ok);
1220 break;
1221
1222 case Token::SEMICOLON:
1223 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001224 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001225
1226 case Token::IF:
1227 stmt = ParseIfStatement(labels, ok);
1228 break;
1229
1230 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001231 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001232 break;
1233
1234 case Token::WHILE:
1235 stmt = ParseWhileStatement(labels, ok);
1236 break;
1237
1238 case Token::FOR:
1239 stmt = ParseForStatement(labels, ok);
1240 break;
1241
1242 case Token::CONTINUE:
1243 stmt = ParseContinueStatement(ok);
1244 break;
1245
1246 case Token::BREAK:
1247 stmt = ParseBreakStatement(labels, ok);
1248 break;
1249
1250 case Token::RETURN:
1251 stmt = ParseReturnStatement(ok);
1252 break;
1253
1254 case Token::WITH:
1255 stmt = ParseWithStatement(labels, ok);
1256 break;
1257
1258 case Token::SWITCH:
1259 stmt = ParseSwitchStatement(labels, ok);
1260 break;
1261
1262 case Token::THROW:
1263 stmt = ParseThrowStatement(ok);
1264 break;
1265
1266 case Token::TRY: {
1267 // NOTE: It is somewhat complicated to have labels on
1268 // try-statements. When breaking out of a try-finally statement,
1269 // one must take great care not to treat it as a
1270 // fall-through. It is much easier just to wrap the entire
1271 // try-statement in a statement block and put the labels there
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001272 Block* result = new Block(labels, 1, false);
1273 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001274 TryStatement* statement = ParseTryStatement(CHECK_OK);
1275 if (statement) {
1276 statement->set_statement_pos(statement_pos);
1277 }
1278 if (result) result->AddStatement(statement);
1279 return result;
1280 }
1281
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001282 case Token::FUNCTION: {
1283 // In strict mode, FunctionDeclaration is only allowed in the context
1284 // of SourceElements.
1285 if (temp_scope_->StrictMode()) {
1286 ReportMessageAt(scanner().peek_location(), "strict_function",
1287 Vector<const char*>::empty());
1288 *ok = false;
1289 return NULL;
1290 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001292 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001293
1294 case Token::NATIVE:
1295 return ParseNativeDeclaration(ok);
1296
1297 case Token::DEBUGGER:
1298 stmt = ParseDebuggerStatement(ok);
1299 break;
1300
1301 default:
1302 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1303 }
1304
1305 // Store the source position of the statement
1306 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1307 return stmt;
1308}
1309
1310
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001311VariableProxy* Parser::Declare(Handle<String> name,
1312 Variable::Mode mode,
1313 FunctionLiteral* fun,
1314 bool resolve,
1315 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001316 Variable* var = NULL;
1317 // If we are inside a function, a declaration of a variable
1318 // is a truly local variable, and the scope of the variable
1319 // is always the function scope.
1320
1321 // If a function scope exists, then we can statically declare this
1322 // variable and also set its mode. In any case, a Declaration node
1323 // will be added to the scope so that the declaration can be added
1324 // to the corresponding activation frame at runtime if necessary.
1325 // For instance declarations inside an eval scope need to be added
1326 // to the calling function context.
1327 if (top_scope_->is_function_scope()) {
1328 // Declare the variable in the function scope.
1329 var = top_scope_->LocalLookup(name);
1330 if (var == NULL) {
1331 // Declare the name.
1332 var = top_scope_->DeclareLocal(name, mode);
1333 } else {
1334 // The name was declared before; check for conflicting
1335 // re-declarations. If the previous declaration was a const or the
1336 // current declaration is a const then we have a conflict. There is
1337 // similar code in runtime.cc in the Declare functions.
1338 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1339 // We only have vars and consts in declarations.
1340 ASSERT(var->mode() == Variable::VAR ||
1341 var->mode() == Variable::CONST);
1342 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1343 Handle<String> type_string =
1344 Factory::NewStringFromUtf8(CStrVector(type), TENURED);
1345 Expression* expression =
1346 NewThrowTypeError(Factory::redeclaration_symbol(),
1347 type_string, name);
1348 top_scope_->SetIllegalRedeclaration(expression);
1349 }
1350 }
1351 }
1352
1353 // We add a declaration node for every declaration. The compiler
1354 // will only generate code if necessary. In particular, declarations
1355 // for inner local variables that do not represent functions won't
1356 // result in any generated code.
1357 //
1358 // Note that we always add an unresolved proxy even if it's not
1359 // used, simply because we don't know in this method (w/o extra
1360 // parameters) if the proxy is needed or not. The proxy will be
1361 // bound during variable resolution time unless it was pre-bound
1362 // below.
1363 //
1364 // WARNING: This will lead to multiple declaration nodes for the
1365 // same variable if it is declared several times. This is not a
1366 // semantic issue as long as we keep the source order, but it may be
1367 // a performance issue since it may lead to repeated
1368 // Runtime::DeclareContextSlot() calls.
1369 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001370 top_scope_->AddDeclaration(new Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001371
1372 // For global const variables we bind the proxy to a variable.
1373 if (mode == Variable::CONST && top_scope_->is_global_scope()) {
1374 ASSERT(resolve); // should be set by all callers
1375 Variable::Kind kind = Variable::NORMAL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001376 var = new Variable(top_scope_, name, Variable::CONST, true, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001377 }
1378
1379 // If requested and we have a local variable, bind the proxy to the variable
1380 // at parse-time. This is used for functions (and consts) declared inside
1381 // statements: the corresponding function (or const) variable must be in the
1382 // function scope and not a statement-local scope, e.g. as provided with a
1383 // 'with' statement:
1384 //
1385 // with (obj) {
1386 // function f() {}
1387 // }
1388 //
1389 // which is translated into:
1390 //
1391 // with (obj) {
1392 // // in this case this is not: 'var f; f = function () {};'
1393 // var f = function () {};
1394 // }
1395 //
1396 // Note that if 'f' is accessed from inside the 'with' statement, it
1397 // will be allocated in the context (because we must be able to look
1398 // it up dynamically) but it will also be accessed statically, i.e.,
1399 // with a context slot index and a context chain length for this
1400 // initialization code. Thus, inside the 'with' statement, we need
1401 // both access to the static and the dynamic context chain; the
1402 // runtime needs to provide both.
1403 if (resolve && var != NULL) proxy->BindTo(var);
1404
1405 return proxy;
1406}
1407
1408
1409// Language extension which is only enabled for source files loaded
1410// through the API's extension mechanism. A native function
1411// declaration is resolved by looking up the function through a
1412// callback provided by the extension.
1413Statement* Parser::ParseNativeDeclaration(bool* ok) {
1414 if (extension_ == NULL) {
1415 ReportUnexpectedToken(Token::NATIVE);
1416 *ok = false;
1417 return NULL;
1418 }
1419
1420 Expect(Token::NATIVE, CHECK_OK);
1421 Expect(Token::FUNCTION, CHECK_OK);
1422 Handle<String> name = ParseIdentifier(CHECK_OK);
1423 Expect(Token::LPAREN, CHECK_OK);
1424 bool done = (peek() == Token::RPAREN);
1425 while (!done) {
1426 ParseIdentifier(CHECK_OK);
1427 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001428 if (!done) {
1429 Expect(Token::COMMA, CHECK_OK);
1430 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001431 }
1432 Expect(Token::RPAREN, CHECK_OK);
1433 Expect(Token::SEMICOLON, CHECK_OK);
1434
Steve Blocka7e24c12009-10-30 11:49:00 +00001435 // Make sure that the function containing the native declaration
1436 // isn't lazily compiled. The extension structures are only
1437 // accessible while parsing the first time not when reparsing
1438 // because of lazy compilation.
1439 top_scope_->ForceEagerCompilation();
1440
1441 // Compute the function template for the native function.
1442 v8::Handle<v8::FunctionTemplate> fun_template =
1443 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1444 ASSERT(!fun_template.IsEmpty());
1445
Steve Block6ded16b2010-05-10 14:33:55 +01001446 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001447 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1448 const int literals = fun->NumberOfLiterals();
1449 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001450 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001451 Handle<SharedFunctionInfo> shared =
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001452 Factory::NewSharedFunctionInfo(name, literals, code,
1453 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001454 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001455
Steve Block6ded16b2010-05-10 14:33:55 +01001456 // Copy the function data to the shared function info.
1457 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001458 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001459 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001460
1461 // TODO(1240846): It's weird that native function declarations are
1462 // introduced dynamically when we meet their declarations, whereas
1463 // other functions are setup when entering the surrounding scope.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001464 SharedFunctionInfoLiteral* lit = new SharedFunctionInfoLiteral(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001465 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001466 return new ExpressionStatement(
1467 new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001468}
1469
1470
1471Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1472 // FunctionDeclaration ::
1473 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1474 Expect(Token::FUNCTION, CHECK_OK);
1475 int function_token_position = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01001476 bool is_reserved = false;
1477 Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001478 FunctionLiteral* fun = ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01001479 is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001480 function_token_position,
1481 DECLARATION,
1482 CHECK_OK);
1483 // Even if we're not at the top-level of the global or a function
1484 // scope, we treat is as such and introduce the function with it's
1485 // initial value upon entering the corresponding scope.
1486 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001487 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001488}
1489
1490
1491Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1492 // Block ::
1493 // '{' Statement* '}'
1494
1495 // Note that a Block does not introduce a new execution scope!
1496 // (ECMA-262, 3rd, 12.2)
1497 //
1498 // Construct block expecting 16 statements.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001499 Block* result = new Block(labels, 16, false);
1500 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001501 Expect(Token::LBRACE, CHECK_OK);
1502 while (peek() != Token::RBRACE) {
1503 Statement* stat = ParseStatement(NULL, CHECK_OK);
1504 if (stat && !stat->IsEmpty()) result->AddStatement(stat);
1505 }
1506 Expect(Token::RBRACE, CHECK_OK);
1507 return result;
1508}
1509
1510
1511Block* Parser::ParseVariableStatement(bool* ok) {
1512 // VariableStatement ::
1513 // VariableDeclarations ';'
1514
1515 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature
1516 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK);
1517 ExpectSemicolon(CHECK_OK);
1518 return result;
1519}
1520
Steve Block1e0659c2011-05-24 12:43:12 +01001521static bool IsEvalOrArguments(Handle<String> string) {
1522 return string.is_identical_to(Factory::eval_symbol()) ||
1523 string.is_identical_to(Factory::arguments_symbol());
1524}
Steve Blocka7e24c12009-10-30 11:49:00 +00001525
1526// If the variable declaration declares exactly one non-const
1527// variable, then *var is set to that variable. In all other cases,
1528// *var is untouched; in particular, it is the caller's responsibility
1529// to initialize it properly. This mechanism is used for the parsing
1530// of 'for-in' loops.
1531Block* Parser::ParseVariableDeclarations(bool accept_IN,
1532 Expression** var,
1533 bool* ok) {
1534 // VariableDeclarations ::
1535 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1536
1537 Variable::Mode mode = Variable::VAR;
1538 bool is_const = false;
1539 if (peek() == Token::VAR) {
1540 Consume(Token::VAR);
1541 } else if (peek() == Token::CONST) {
1542 Consume(Token::CONST);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001543 if (temp_scope_->StrictMode()) {
1544 ReportMessage("strict_const", Vector<const char*>::empty());
1545 *ok = false;
1546 return NULL;
1547 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001548 mode = Variable::CONST;
1549 is_const = true;
1550 } else {
1551 UNREACHABLE(); // by current callers
1552 }
1553
1554 // The scope of a variable/const declared anywhere inside a function
1555 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1556 // transform a source-level variable/const declaration into a (Function)
1557 // Scope declaration, and rewrite the source-level initialization into an
1558 // assignment statement. We use a block to collect multiple assignments.
1559 //
1560 // We mark the block as initializer block because we don't want the
1561 // rewriter to add a '.result' assignment to such a block (to get compliant
1562 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1563 // reasons when pretty-printing. Also, unless an assignment (initialization)
1564 // is inside an initializer block, it is ignored.
1565 //
1566 // Create new block with one expected declaration.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001567 Block* block = new Block(NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001568 VariableProxy* last_var = NULL; // the last variable declared
1569 int nvars = 0; // the number of variables declared
1570 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001571 if (fni_ != NULL) fni_->Enter();
1572
Steve Blocka7e24c12009-10-30 11:49:00 +00001573 // Parse variable name.
1574 if (nvars > 0) Consume(Token::COMMA);
1575 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001576 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001577
Steve Block1e0659c2011-05-24 12:43:12 +01001578 // Strict mode variables may not be named eval or arguments
1579 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
1580 ReportMessage("strict_var_name", Vector<const char*>::empty());
1581 *ok = false;
1582 return NULL;
1583 }
1584
Steve Blocka7e24c12009-10-30 11:49:00 +00001585 // Declare variable.
1586 // Note that we *always* must treat the initial value via a separate init
1587 // assignment for variables and constants because the value must be assigned
1588 // when the variable is encountered in the source. But the variable/constant
1589 // is declared (and set to 'undefined') upon entering the function within
1590 // which the variable or constant is declared. Only function variables have
1591 // an initial value in the declaration (because they are initialized upon
1592 // entering the function).
1593 //
1594 // If we have a const declaration, in an inner scope, the proxy is always
1595 // bound to the declared variable (independent of possibly surrounding with
1596 // statements).
1597 last_var = Declare(name, mode, NULL,
1598 is_const /* always bound for CONST! */,
1599 CHECK_OK);
1600 nvars++;
1601
1602 // Parse initialization expression if present and/or needed. A
1603 // declaration of the form:
1604 //
1605 // var v = x;
1606 //
1607 // is syntactic sugar for:
1608 //
1609 // var v; v = x;
1610 //
1611 // In particular, we need to re-lookup 'v' as it may be a
1612 // different 'v' than the 'v' in the declaration (if we are inside
1613 // a 'with' statement that makes a object property with name 'v'
1614 // visible).
1615 //
1616 // However, note that const declarations are different! A const
1617 // declaration of the form:
1618 //
1619 // const c = x;
1620 //
1621 // is *not* syntactic sugar for:
1622 //
1623 // const c; c = x;
1624 //
1625 // The "variable" c initialized to x is the same as the declared
1626 // one - there is no re-lookup (see the last parameter of the
1627 // Declare() call above).
1628
1629 Expression* value = NULL;
1630 int position = -1;
1631 if (peek() == Token::ASSIGN) {
1632 Expect(Token::ASSIGN, CHECK_OK);
1633 position = scanner().location().beg_pos;
1634 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001635 // Don't infer if it is "a = function(){...}();"-like expression.
1636 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer();
Steve Blocka7e24c12009-10-30 11:49:00 +00001637 }
1638
1639 // Make sure that 'const c' actually initializes 'c' to undefined
1640 // even though it seems like a stupid thing to do.
1641 if (value == NULL && is_const) {
1642 value = GetLiteralUndefined();
1643 }
1644
1645 // Global variable declarations must be compiled in a specific
1646 // way. When the script containing the global variable declaration
1647 // is entered, the global variable must be declared, so that if it
1648 // doesn't exist (not even in a prototype of the global object) it
1649 // gets created with an initial undefined value. This is handled
1650 // by the declarations part of the function representing the
1651 // top-level global code; see Runtime::DeclareGlobalVariable. If
1652 // it already exists (in the object or in a prototype), it is
1653 // *not* touched until the variable declaration statement is
1654 // executed.
1655 //
1656 // Executing the variable declaration statement will always
1657 // guarantee to give the global object a "local" variable; a
1658 // variable defined in the global object and not in any
1659 // prototype. This way, global variable declarations can shadow
1660 // properties in the prototype chain, but only after the variable
1661 // declaration statement has been executed. This is important in
1662 // browsers where the global object (window) has lots of
1663 // properties defined in prototype objects.
1664
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001665 if (top_scope_->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001666 // Compute the arguments for the runtime call.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001667 ZoneList<Expression*>* arguments = new ZoneList<Expression*>(3);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001668 arguments->Add(new Literal(name)); // we have at least 1 parameter
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001669 CallRuntime* initialize;
1670
1671 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001672 arguments->Add(value);
1673 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001674
1675 // Construct the call to Runtime_InitializeConstGlobal
1676 // and add it to the initialization statement block.
1677 // Note that the function does different things depending on
1678 // the number of arguments (1 or 2).
Steve Blocka7e24c12009-10-30 11:49:00 +00001679 initialize =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001680 new CallRuntime(
1681 Factory::InitializeConstGlobal_symbol(),
1682 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1683 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001684 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001685 // Add strict mode.
1686 // We may want to pass singleton to avoid Literal allocations.
1687 arguments->Add(NewNumberLiteral(
1688 temp_scope_->StrictMode() ? kStrictMode : kNonStrictMode));
1689
1690 // Be careful not to assign a value to the global variable if
1691 // we're in a with. The initialization value should not
1692 // necessarily be stored in the global object in that case,
1693 // which is why we need to generate a separate assignment node.
1694 if (value != NULL && !inside_with()) {
1695 arguments->Add(value);
1696 value = NULL; // zap the value to avoid the unnecessary assignment
1697 }
1698
1699 // Construct the call to Runtime_InitializeVarGlobal
1700 // and add it to the initialization statement block.
1701 // Note that the function does different things depending on
1702 // the number of arguments (2 or 3).
Steve Blocka7e24c12009-10-30 11:49:00 +00001703 initialize =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001704 new CallRuntime(
1705 Factory::InitializeVarGlobal_symbol(),
1706 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1707 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001708 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001709
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001710 block->AddStatement(new ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001711 }
1712
1713 // Add an assignment node to the initialization statement block if
1714 // we still have a pending initialization value. We must distinguish
1715 // between variables and constants: Variable initializations are simply
1716 // assignments (with all the consequences if they are inside a 'with'
1717 // statement - they may change a 'with' object property). Constant
1718 // initializations always assign to the declared constant which is
1719 // always at the function scope level. This is only relevant for
1720 // dynamically looked-up variables and constants (the start context
1721 // for constant lookups is always the function context, while it is
1722 // the top context for variables). Sigh...
1723 if (value != NULL) {
1724 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001725 Assignment* assignment = new Assignment(op, last_var, value, position);
1726 if (block) block->AddStatement(new ExpressionStatement(assignment));
Steve Blocka7e24c12009-10-30 11:49:00 +00001727 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001728
1729 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001730 } while (peek() == Token::COMMA);
1731
1732 if (!is_const && nvars == 1) {
1733 // We have a single, non-const variable.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001734 ASSERT(last_var != NULL);
1735 *var = last_var;
Steve Blocka7e24c12009-10-30 11:49:00 +00001736 }
1737
1738 return block;
1739}
1740
1741
1742static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1743 ASSERT(!label.is_null());
1744 if (labels != NULL)
1745 for (int i = labels->length(); i-- > 0; )
1746 if (labels->at(i).is_identical_to(label))
1747 return true;
1748
1749 return false;
1750}
1751
1752
1753Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1754 bool* ok) {
1755 // ExpressionStatement | LabelledStatement ::
1756 // Expression ';'
1757 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001758 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001759 Expression* expr = ParseExpression(true, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001760 if (peek() == Token::COLON && starts_with_idenfifier && expr &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001761 expr->AsVariableProxy() != NULL &&
1762 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001763 // Expression is a single identifier, and not, e.g., a parenthesized
1764 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001765 VariableProxy* var = expr->AsVariableProxy();
1766 Handle<String> label = var->name();
1767 // TODO(1240780): We don't check for redeclaration of labels
1768 // during preparsing since keeping track of the set of active
1769 // labels requires nontrivial changes to the way scopes are
1770 // structured. However, these are probably changes we want to
1771 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001772 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1773 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1774 const char* elms[2] = { "Label", *c_string };
1775 Vector<const char*> args(elms, 2);
1776 ReportMessage("redeclaration", args);
1777 *ok = false;
1778 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001779 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001780 if (labels == NULL) labels = new ZoneStringList(4);
1781 labels->Add(label);
1782 // Remove the "ghost" variable that turned out to be a label
1783 // from the top scope. This way, we don't try to resolve it
1784 // during the scope processing.
1785 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001786 Expect(Token::COLON, CHECK_OK);
1787 return ParseStatement(labels, ok);
1788 }
1789
1790 // Parsed expression statement.
1791 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001792 return new ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001793}
1794
1795
1796IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1797 // IfStatement ::
1798 // 'if' '(' Expression ')' Statement ('else' Statement)?
1799
1800 Expect(Token::IF, CHECK_OK);
1801 Expect(Token::LPAREN, CHECK_OK);
1802 Expression* condition = ParseExpression(true, CHECK_OK);
1803 Expect(Token::RPAREN, CHECK_OK);
1804 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1805 Statement* else_statement = NULL;
1806 if (peek() == Token::ELSE) {
1807 Next();
1808 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001809 } else {
1810 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001811 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001812 return new IfStatement(condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001813}
1814
1815
1816Statement* Parser::ParseContinueStatement(bool* ok) {
1817 // ContinueStatement ::
1818 // 'continue' Identifier? ';'
1819
1820 Expect(Token::CONTINUE, CHECK_OK);
1821 Handle<String> label = Handle<String>::null();
1822 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001823 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001824 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1825 label = ParseIdentifier(CHECK_OK);
1826 }
1827 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001828 target = LookupContinueTarget(label, CHECK_OK);
1829 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001830 // Illegal continue statement.
1831 const char* message = "illegal_continue";
1832 Vector<Handle<String> > args;
1833 if (!label.is_null()) {
1834 message = "unknown_label";
1835 args = Vector<Handle<String> >(&label, 1);
1836 }
1837 ReportMessageAt(scanner().location(), message, args);
1838 *ok = false;
1839 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001840 }
1841 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001842 return new ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001843}
1844
1845
1846Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1847 // BreakStatement ::
1848 // 'break' Identifier? ';'
1849
1850 Expect(Token::BREAK, CHECK_OK);
1851 Handle<String> label;
1852 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001853 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001854 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1855 label = ParseIdentifier(CHECK_OK);
1856 }
1857 // Parse labeled break statements that target themselves into
1858 // empty statements, e.g. 'l1: l2: l3: break l2;'
1859 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001860 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001861 }
1862 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001863 target = LookupBreakTarget(label, CHECK_OK);
1864 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001865 // Illegal break statement.
1866 const char* message = "illegal_break";
1867 Vector<Handle<String> > args;
1868 if (!label.is_null()) {
1869 message = "unknown_label";
1870 args = Vector<Handle<String> >(&label, 1);
1871 }
1872 ReportMessageAt(scanner().location(), message, args);
1873 *ok = false;
1874 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001875 }
1876 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001877 return new BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001878}
1879
1880
1881Statement* Parser::ParseReturnStatement(bool* ok) {
1882 // ReturnStatement ::
1883 // 'return' Expression? ';'
1884
1885 // Consume the return token. It is necessary to do the before
1886 // reporting any errors on it, because of the way errors are
1887 // reported (underlining).
1888 Expect(Token::RETURN, CHECK_OK);
1889
1890 // An ECMAScript program is considered syntactically incorrect if it
1891 // contains a return statement that is not within the body of a
1892 // function. See ECMA-262, section 12.9, page 67.
1893 //
1894 // To be consistent with KJS we report the syntax error at runtime.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001895 if (!top_scope_->is_function_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001896 Handle<String> type = Factory::illegal_return_symbol();
1897 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001898 return new ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001899 }
1900
1901 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001902 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001903 tok == Token::SEMICOLON ||
1904 tok == Token::RBRACE ||
1905 tok == Token::EOS) {
1906 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001907 return new ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001908 }
1909
1910 Expression* expr = ParseExpression(true, CHECK_OK);
1911 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001912 return new ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001913}
1914
1915
1916Block* Parser::WithHelper(Expression* obj,
1917 ZoneStringList* labels,
1918 bool is_catch_block,
1919 bool* ok) {
1920 // Parse the statement and collect escaping labels.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001921 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001922 TargetCollector collector(target_list);
1923 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001924 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001925 with_nesting_level_++;
1926 top_scope_->RecordWithStatement();
1927 stat = ParseStatement(labels, CHECK_OK);
1928 with_nesting_level_--;
1929 }
1930 // Create resulting block with two statements.
1931 // 1: Evaluate the with expression.
1932 // 2: The try-finally block evaluating the body.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001933 Block* result = new Block(NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001934
1935 if (result != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001936 result->AddStatement(new WithEnterStatement(obj, is_catch_block));
Steve Blocka7e24c12009-10-30 11:49:00 +00001937
1938 // Create body block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001939 Block* body = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001940 body->AddStatement(stat);
1941
1942 // Create exit block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001943 Block* exit = new Block(NULL, 1, false);
1944 exit->AddStatement(new WithExitStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00001945
1946 // Return a try-finally statement.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001947 TryFinallyStatement* wrapper = new TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001948 wrapper->set_escaping_targets(collector.targets());
1949 result->AddStatement(wrapper);
1950 }
1951 return result;
1952}
1953
1954
1955Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
1956 // WithStatement ::
1957 // 'with' '(' Expression ')' Statement
1958
1959 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001960
1961 if (temp_scope_->StrictMode()) {
1962 ReportMessage("strict_mode_with", Vector<const char*>::empty());
1963 *ok = false;
1964 return NULL;
1965 }
1966
Steve Blocka7e24c12009-10-30 11:49:00 +00001967 Expect(Token::LPAREN, CHECK_OK);
1968 Expression* expr = ParseExpression(true, CHECK_OK);
1969 Expect(Token::RPAREN, CHECK_OK);
1970
1971 return WithHelper(expr, labels, false, CHECK_OK);
1972}
1973
1974
1975CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1976 // CaseClause ::
1977 // 'case' Expression ':' Statement*
1978 // 'default' ':' Statement*
1979
1980 Expression* label = NULL; // NULL expression indicates default case
1981 if (peek() == Token::CASE) {
1982 Expect(Token::CASE, CHECK_OK);
1983 label = ParseExpression(true, CHECK_OK);
1984 } else {
1985 Expect(Token::DEFAULT, CHECK_OK);
1986 if (*default_seen_ptr) {
1987 ReportMessage("multiple_defaults_in_switch",
1988 Vector<const char*>::empty());
1989 *ok = false;
1990 return NULL;
1991 }
1992 *default_seen_ptr = true;
1993 }
1994 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001995 int pos = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001996 ZoneList<Statement*>* statements = new ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001997 while (peek() != Token::CASE &&
1998 peek() != Token::DEFAULT &&
1999 peek() != Token::RBRACE) {
2000 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002001 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00002002 }
2003
Ben Murdochb0fe1622011-05-05 13:52:32 +01002004 return new CaseClause(label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002005}
2006
2007
2008SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2009 bool* ok) {
2010 // SwitchStatement ::
2011 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2012
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002013 SwitchStatement* statement = new SwitchStatement(labels);
2014 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002015
2016 Expect(Token::SWITCH, CHECK_OK);
2017 Expect(Token::LPAREN, CHECK_OK);
2018 Expression* tag = ParseExpression(true, CHECK_OK);
2019 Expect(Token::RPAREN, CHECK_OK);
2020
2021 bool default_seen = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002022 ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002023 Expect(Token::LBRACE, CHECK_OK);
2024 while (peek() != Token::RBRACE) {
2025 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002026 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002027 }
2028 Expect(Token::RBRACE, CHECK_OK);
2029
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002030 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002031 return statement;
2032}
2033
2034
2035Statement* Parser::ParseThrowStatement(bool* ok) {
2036 // ThrowStatement ::
2037 // 'throw' Expression ';'
2038
2039 Expect(Token::THROW, CHECK_OK);
2040 int pos = scanner().location().beg_pos;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002041 if (scanner().has_line_terminator_before_next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002042 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2043 *ok = false;
2044 return NULL;
2045 }
2046 Expression* exception = ParseExpression(true, CHECK_OK);
2047 ExpectSemicolon(CHECK_OK);
2048
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002049 return new ExpressionStatement(new Throw(exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002050}
2051
2052
2053TryStatement* Parser::ParseTryStatement(bool* ok) {
2054 // TryStatement ::
2055 // 'try' Block Catch
2056 // 'try' Block Finally
2057 // 'try' Block Catch Finally
2058 //
2059 // Catch ::
2060 // 'catch' '(' Identifier ')' Block
2061 //
2062 // Finally ::
2063 // 'finally' Block
2064
2065 Expect(Token::TRY, CHECK_OK);
2066
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002067 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002068 TargetCollector collector(target_list);
2069 Block* try_block;
2070
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002071 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002072 try_block = ParseBlock(NULL, CHECK_OK);
2073 }
2074
2075 Block* catch_block = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002076 Variable* catch_var = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002077 Block* finally_block = NULL;
2078
2079 Token::Value tok = peek();
2080 if (tok != Token::CATCH && tok != Token::FINALLY) {
2081 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2082 *ok = false;
2083 return NULL;
2084 }
2085
2086 // If we can break out from the catch block and there is a finally block,
2087 // then we will need to collect jump targets from the catch block. Since
2088 // we don't know yet if there will be a finally block, we always collect
2089 // the jump targets.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002090 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002091 TargetCollector catch_collector(catch_target_list);
2092 bool has_catch = false;
2093 if (tok == Token::CATCH) {
2094 has_catch = true;
2095 Consume(Token::CATCH);
2096
2097 Expect(Token::LPAREN, CHECK_OK);
2098 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002099
2100 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
2101 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2102 *ok = false;
2103 return NULL;
2104 }
2105
Steve Blocka7e24c12009-10-30 11:49:00 +00002106 Expect(Token::RPAREN, CHECK_OK);
2107
2108 if (peek() == Token::LBRACE) {
2109 // Allocate a temporary for holding the finally state while
2110 // executing the finally block.
2111 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002112 Literal* name_literal = new Literal(name);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002113 VariableProxy* catch_var_use = new VariableProxy(catch_var);
2114 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002115 { Target target(&this->target_stack_, &catch_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002116 catch_block = WithHelper(obj, NULL, true, CHECK_OK);
2117 }
2118 } else {
2119 Expect(Token::LBRACE, CHECK_OK);
2120 }
2121
2122 tok = peek();
2123 }
2124
2125 if (tok == Token::FINALLY || !has_catch) {
2126 Consume(Token::FINALLY);
2127 // Declare a variable for holding the finally state while
2128 // executing the finally block.
2129 finally_block = ParseBlock(NULL, CHECK_OK);
2130 }
2131
2132 // Simplify the AST nodes by converting:
2133 // 'try { } catch { } finally { }'
2134 // to:
2135 // 'try { try { } catch { } } finally { }'
2136
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002137 if (catch_block != NULL && finally_block != NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002138 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
Steve Block3ce2e202009-11-05 08:53:23 +00002139 TryCatchStatement* statement =
Ben Murdochb0fe1622011-05-05 13:52:32 +01002140 new TryCatchStatement(try_block, catch_var_defn, catch_block);
Steve Blocka7e24c12009-10-30 11:49:00 +00002141 statement->set_escaping_targets(collector.targets());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002142 try_block = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002143 try_block->AddStatement(statement);
2144 catch_block = NULL;
2145 }
2146
2147 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002148 if (catch_block != NULL) {
2149 ASSERT(finally_block == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002150 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
2151 result = new TryCatchStatement(try_block, catch_var_defn, catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002152 result->set_escaping_targets(collector.targets());
2153 } else {
2154 ASSERT(finally_block != NULL);
2155 result = new TryFinallyStatement(try_block, finally_block);
2156 // Add the jump targets of the try block and the catch block.
2157 for (int i = 0; i < collector.targets()->length(); i++) {
2158 catch_collector.AddTarget(collector.targets()->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002159 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002160 result->set_escaping_targets(catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002161 }
2162
2163 return result;
2164}
2165
2166
Steve Block3ce2e202009-11-05 08:53:23 +00002167DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2168 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002169 // DoStatement ::
2170 // 'do' Statement 'while' '(' Expression ')' ';'
2171
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002172 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002173 DoWhileStatement* loop = new DoWhileStatement(labels);
2174 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002175
2176 Expect(Token::DO, CHECK_OK);
2177 Statement* body = ParseStatement(NULL, CHECK_OK);
2178 Expect(Token::WHILE, CHECK_OK);
2179 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002180
2181 if (loop != NULL) {
2182 int position = scanner().location().beg_pos;
2183 loop->set_condition_position(position);
2184 }
2185
Steve Blocka7e24c12009-10-30 11:49:00 +00002186 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002187 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 Expect(Token::RPAREN, CHECK_OK);
2189
2190 // Allow do-statements to be terminated with and without
2191 // semi-colons. This allows code such as 'do;while(0)return' to
2192 // parse, which would not be the case if we had used the
2193 // ExpectSemicolon() functionality here.
2194 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2195
Steve Block3ce2e202009-11-05 08:53:23 +00002196 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002197 return loop;
2198}
2199
2200
Steve Block3ce2e202009-11-05 08:53:23 +00002201WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002202 // WhileStatement ::
2203 // 'while' '(' Expression ')' Statement
2204
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002205 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002206 WhileStatement* loop = new WhileStatement(labels);
2207 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002208
2209 Expect(Token::WHILE, CHECK_OK);
2210 Expect(Token::LPAREN, CHECK_OK);
2211 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002212 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002213 Expect(Token::RPAREN, CHECK_OK);
2214 Statement* body = ParseStatement(NULL, CHECK_OK);
2215
Steve Block3ce2e202009-11-05 08:53:23 +00002216 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002217 return loop;
2218}
2219
2220
2221Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2222 // ForStatement ::
2223 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2224
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002225 temp_scope_->AddLoop();
Steve Blocka7e24c12009-10-30 11:49:00 +00002226 Statement* init = NULL;
2227
2228 Expect(Token::FOR, CHECK_OK);
2229 Expect(Token::LPAREN, CHECK_OK);
2230 if (peek() != Token::SEMICOLON) {
2231 if (peek() == Token::VAR || peek() == Token::CONST) {
2232 Expression* each = NULL;
2233 Block* variable_statement =
2234 ParseVariableDeclarations(false, &each, CHECK_OK);
2235 if (peek() == Token::IN && each != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002236 ForInStatement* loop = new ForInStatement(labels);
2237 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002238
2239 Expect(Token::IN, CHECK_OK);
2240 Expression* enumerable = ParseExpression(true, CHECK_OK);
2241 Expect(Token::RPAREN, CHECK_OK);
2242
2243 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002244 loop->Initialize(each, enumerable, body);
2245 Block* result = new Block(NULL, 2, false);
2246 result->AddStatement(variable_statement);
2247 result->AddStatement(loop);
2248 // Parsed for-in loop w/ variable/const declaration.
2249 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002250 } else {
2251 init = variable_statement;
2252 }
2253
2254 } else {
2255 Expression* expression = ParseExpression(false, CHECK_OK);
2256 if (peek() == Token::IN) {
2257 // Signal a reference error if the expression is an invalid
2258 // left-hand side expression. We could report this as a syntax
2259 // error here but for compatibility with JSC we choose to report
2260 // the error at runtime.
2261 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2262 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
2263 expression = NewThrowReferenceError(type);
2264 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002265 ForInStatement* loop = new ForInStatement(labels);
2266 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002267
2268 Expect(Token::IN, CHECK_OK);
2269 Expression* enumerable = ParseExpression(true, CHECK_OK);
2270 Expect(Token::RPAREN, CHECK_OK);
2271
2272 Statement* body = ParseStatement(NULL, CHECK_OK);
2273 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002274 // Parsed for-in loop.
2275 return loop;
2276
2277 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002278 init = new ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002279 }
2280 }
2281 }
2282
2283 // Standard 'for' loop
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002284 ForStatement* loop = new ForStatement(labels);
2285 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002286
2287 // Parsed initializer at this point.
2288 Expect(Token::SEMICOLON, CHECK_OK);
2289
2290 Expression* cond = NULL;
2291 if (peek() != Token::SEMICOLON) {
2292 cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002293 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002294 }
2295 Expect(Token::SEMICOLON, CHECK_OK);
2296
2297 Statement* next = NULL;
2298 if (peek() != Token::RPAREN) {
2299 Expression* exp = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002300 next = new ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002301 }
2302 Expect(Token::RPAREN, CHECK_OK);
2303
2304 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002305 if (loop) loop->Initialize(init, cond, next, body);
2306 return loop;
2307}
2308
2309
2310// Precedence = 1
2311Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2312 // Expression ::
2313 // AssignmentExpression
2314 // Expression ',' AssignmentExpression
2315
2316 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2317 while (peek() == Token::COMMA) {
2318 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002319 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002320 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002321 result = new BinaryOperation(Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002322 }
2323 return result;
2324}
2325
2326
2327// Precedence = 2
2328Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2329 // AssignmentExpression ::
2330 // ConditionalExpression
2331 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2332
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002333 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002334 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2335
2336 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002337 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002338 // Parsed conditional expression only (no assignment).
2339 return expression;
2340 }
2341
2342 // Signal a reference error if the expression is an invalid left-hand
2343 // side expression. We could report this as a syntax error here but
2344 // for compatibility with JSC we choose to report the error at
2345 // runtime.
2346 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2347 Handle<String> type = Factory::invalid_lhs_in_assignment_symbol();
2348 expression = NewThrowReferenceError(type);
2349 }
2350
Steve Block1e0659c2011-05-24 12:43:12 +01002351 if (temp_scope_->StrictMode()) {
2352 // Assignment to eval or arguments is disallowed in strict mode.
2353 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2354 }
2355
Steve Blocka7e24c12009-10-30 11:49:00 +00002356 Token::Value op = Next(); // Get assignment operator.
2357 int pos = scanner().location().beg_pos;
2358 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2359
2360 // TODO(1231235): We try to estimate the set of properties set by
2361 // constructors. We define a new property whenever there is an
2362 // assignment to a property of 'this'. We should probably only add
2363 // properties if we haven't seen them before. Otherwise we'll
2364 // probably overestimate the number of properties.
2365 Property* property = expression ? expression->AsProperty() : NULL;
2366 if (op == Token::ASSIGN &&
2367 property != NULL &&
2368 property->obj()->AsVariableProxy() != NULL &&
2369 property->obj()->AsVariableProxy()->is_this()) {
2370 temp_scope_->AddProperty();
2371 }
2372
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002373 // If we assign a function literal to a property we pretenure the
2374 // literal so it can be added as a constant function property.
2375 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2376 right->AsFunctionLiteral()->set_pretenure(true);
2377 }
2378
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002379 if (fni_ != NULL) {
2380 // Check if the right hand side is a call to avoid inferring a
2381 // name if we're dealing with "a = function(){...}();"-like
2382 // expression.
2383 if ((op == Token::INIT_VAR
2384 || op == Token::INIT_CONST
2385 || op == Token::ASSIGN)
2386 && (right->AsCall() == NULL)) {
2387 fni_->Infer();
2388 }
2389 fni_->Leave();
2390 }
2391
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002392 return new Assignment(op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002393}
2394
2395
2396// Precedence = 3
2397Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2398 // ConditionalExpression ::
2399 // LogicalOrExpression
2400 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2401
2402 // We start using the binary expression parser for prec >= 4 only!
2403 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2404 if (peek() != Token::CONDITIONAL) return expression;
2405 Consume(Token::CONDITIONAL);
2406 // In parsing the first assignment expression in conditional
2407 // expressions we always accept the 'in' keyword; see ECMA-262,
2408 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002409 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002410 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2411 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002412 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002413 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002414 return new Conditional(expression, left, right,
2415 left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002416}
2417
2418
2419static int Precedence(Token::Value tok, bool accept_IN) {
2420 if (tok == Token::IN && !accept_IN)
2421 return 0; // 0 precedence will terminate binary expression parsing
2422
2423 return Token::Precedence(tok);
2424}
2425
2426
2427// Precedence >= 4
2428Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2429 ASSERT(prec >= 4);
2430 Expression* x = ParseUnaryExpression(CHECK_OK);
2431 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2432 // prec1 >= 4
2433 while (Precedence(peek(), accept_IN) == prec1) {
2434 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002435 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002436 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2437
2438 // Compute some expressions involving only number literals.
2439 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2440 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2441 double x_val = x->AsLiteral()->handle()->Number();
2442 double y_val = y->AsLiteral()->handle()->Number();
2443
2444 switch (op) {
2445 case Token::ADD:
2446 x = NewNumberLiteral(x_val + y_val);
2447 continue;
2448 case Token::SUB:
2449 x = NewNumberLiteral(x_val - y_val);
2450 continue;
2451 case Token::MUL:
2452 x = NewNumberLiteral(x_val * y_val);
2453 continue;
2454 case Token::DIV:
2455 x = NewNumberLiteral(x_val / y_val);
2456 continue;
2457 case Token::BIT_OR:
2458 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2459 continue;
2460 case Token::BIT_AND:
2461 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2462 continue;
2463 case Token::BIT_XOR:
2464 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2465 continue;
2466 case Token::SHL: {
2467 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2468 x = NewNumberLiteral(value);
2469 continue;
2470 }
2471 case Token::SHR: {
2472 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2473 uint32_t value = DoubleToUint32(x_val) >> shift;
2474 x = NewNumberLiteral(value);
2475 continue;
2476 }
2477 case Token::SAR: {
2478 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2479 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2480 x = NewNumberLiteral(value);
2481 continue;
2482 }
2483 default:
2484 break;
2485 }
2486 }
2487
Steve Blocka7e24c12009-10-30 11:49:00 +00002488 // For now we distinguish between comparisons and other binary
2489 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002490 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002491 if (Token::IsCompareOp(op)) {
2492 // We have a comparison.
2493 Token::Value cmp = op;
2494 switch (op) {
2495 case Token::NE: cmp = Token::EQ; break;
2496 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2497 default: break;
2498 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002499 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002500 if (cmp != op) {
2501 // The comparison was negated - add a NOT.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002502 x = new UnaryOperation(Token::NOT, x);
Steve Blocka7e24c12009-10-30 11:49:00 +00002503 }
2504
2505 } else {
2506 // We have a "normal" binary operation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002507 x = new BinaryOperation(op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002508 }
2509 }
2510 }
2511 return x;
2512}
2513
2514
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002515Expression* Parser::NewCompareNode(Token::Value op,
2516 Expression* x,
2517 Expression* y,
2518 int position) {
2519 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002520 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002521 bool is_strict = (op == Token::EQ_STRICT);
2522 Literal* x_literal = x->AsLiteral();
2523 if (x_literal != NULL && x_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002524 return new CompareToNull(is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002525 }
2526
2527 Literal* y_literal = y->AsLiteral();
2528 if (y_literal != NULL && y_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002529 return new CompareToNull(is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002530 }
2531 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002532 return new CompareOperation(op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002533}
2534
2535
Steve Blocka7e24c12009-10-30 11:49:00 +00002536Expression* Parser::ParseUnaryExpression(bool* ok) {
2537 // UnaryExpression ::
2538 // PostfixExpression
2539 // 'delete' UnaryExpression
2540 // 'void' UnaryExpression
2541 // 'typeof' UnaryExpression
2542 // '++' UnaryExpression
2543 // '--' UnaryExpression
2544 // '+' UnaryExpression
2545 // '-' UnaryExpression
2546 // '~' UnaryExpression
2547 // '!' UnaryExpression
2548
2549 Token::Value op = peek();
2550 if (Token::IsUnaryOp(op)) {
2551 op = Next();
2552 Expression* expression = ParseUnaryExpression(CHECK_OK);
2553
2554 // Compute some expressions involving only number literals.
2555 if (expression != NULL && expression->AsLiteral() &&
2556 expression->AsLiteral()->handle()->IsNumber()) {
2557 double value = expression->AsLiteral()->handle()->Number();
2558 switch (op) {
2559 case Token::ADD:
2560 return expression;
2561 case Token::SUB:
2562 return NewNumberLiteral(-value);
2563 case Token::BIT_NOT:
2564 return NewNumberLiteral(~DoubleToInt32(value));
2565 default: break;
2566 }
2567 }
2568
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002569 // "delete identifier" is a syntax error in strict mode.
2570 if (op == Token::DELETE && temp_scope_->StrictMode()) {
2571 VariableProxy* operand = expression->AsVariableProxy();
2572 if (operand != NULL && !operand->is_this()) {
2573 ReportMessage("strict_delete", Vector<const char*>::empty());
2574 *ok = false;
2575 return NULL;
2576 }
2577 }
2578
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002579 return new UnaryOperation(op, expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002580
2581 } else if (Token::IsCountOp(op)) {
2582 op = Next();
2583 Expression* expression = ParseUnaryExpression(CHECK_OK);
2584 // Signal a reference error if the expression is an invalid
2585 // left-hand side expression. We could report this as a syntax
2586 // error here but for compatibility with JSC we choose to report the
2587 // error at runtime.
2588 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2589 Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
2590 expression = NewThrowReferenceError(type);
2591 }
Steve Block1e0659c2011-05-24 12:43:12 +01002592
2593 if (temp_scope_->StrictMode()) {
2594 // Prefix expression operand in strict mode may not be eval or arguments.
2595 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2596 }
2597
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002598 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002599 IncrementOperation* increment = new IncrementOperation(op, expression);
2600 return new CountOperation(true /* prefix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002601
2602 } else {
2603 return ParsePostfixExpression(ok);
2604 }
2605}
2606
2607
2608Expression* Parser::ParsePostfixExpression(bool* ok) {
2609 // PostfixExpression ::
2610 // LeftHandSideExpression ('++' | '--')?
2611
2612 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002613 if (!scanner().has_line_terminator_before_next() &&
2614 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002615 // Signal a reference error if the expression is an invalid
2616 // left-hand side expression. We could report this as a syntax
2617 // error here but for compatibility with JSC we choose to report the
2618 // error at runtime.
2619 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2620 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
2621 expression = NewThrowReferenceError(type);
2622 }
Steve Block1e0659c2011-05-24 12:43:12 +01002623
2624 if (temp_scope_->StrictMode()) {
2625 // Postfix expression operand in strict mode may not be eval or arguments.
2626 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2627 }
2628
Steve Blocka7e24c12009-10-30 11:49:00 +00002629 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002630 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002631 IncrementOperation* increment = new IncrementOperation(next, expression);
2632 expression = new CountOperation(false /* postfix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002633 }
2634 return expression;
2635}
2636
2637
2638Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2639 // LeftHandSideExpression ::
2640 // (NewExpression | MemberExpression) ...
2641
2642 Expression* result;
2643 if (peek() == Token::NEW) {
2644 result = ParseNewExpression(CHECK_OK);
2645 } else {
2646 result = ParseMemberExpression(CHECK_OK);
2647 }
2648
2649 while (true) {
2650 switch (peek()) {
2651 case Token::LBRACK: {
2652 Consume(Token::LBRACK);
2653 int pos = scanner().location().beg_pos;
2654 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002655 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002656 Expect(Token::RBRACK, CHECK_OK);
2657 break;
2658 }
2659
2660 case Token::LPAREN: {
2661 int pos = scanner().location().beg_pos;
2662 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2663
2664 // Keep track of eval() calls since they disable all local variable
2665 // optimizations.
2666 // The calls that need special treatment are the
2667 // direct (i.e. not aliased) eval calls. These calls are all of the
2668 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002669 // declared in the current scope chain.
2670 // These calls are marked as potentially direct eval calls. Whether
2671 // they are actually direct calls to eval is determined at run time.
2672 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2673 // in the local scope chain. It only matters that it's called "eval",
2674 // is called without a receiver and it refers to the original eval
2675 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002676 VariableProxy* callee = result->AsVariableProxy();
2677 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
2678 Handle<String> name = callee->name();
2679 Variable* var = top_scope_->Lookup(name);
2680 if (var == NULL) {
2681 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002682 }
2683 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002684 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002685 break;
2686 }
2687
2688 case Token::PERIOD: {
2689 Consume(Token::PERIOD);
2690 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002691 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002692 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002693 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002694 break;
2695 }
2696
2697 default:
2698 return result;
2699 }
2700 }
2701}
2702
2703
Steve Blocka7e24c12009-10-30 11:49:00 +00002704Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2705 // NewExpression ::
2706 // ('new')+ MemberExpression
2707
2708 // The grammar for new expressions is pretty warped. The keyword
2709 // 'new' can either be a part of the new expression (where it isn't
2710 // followed by an argument list) or a part of the member expression,
2711 // where it must be followed by an argument list. To accommodate
2712 // this, we parse the 'new' keywords greedily and keep track of how
2713 // many we have parsed. This information is then passed on to the
2714 // member expression parser, which is only allowed to match argument
2715 // lists as long as it has 'new' prefixes left
2716 Expect(Token::NEW, CHECK_OK);
2717 PositionStack::Element pos(stack, scanner().location().beg_pos);
2718
2719 Expression* result;
2720 if (peek() == Token::NEW) {
2721 result = ParseNewPrefix(stack, CHECK_OK);
2722 } else {
2723 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2724 }
2725
2726 if (!stack->is_empty()) {
2727 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002728 result = new CallNew(result, new ZoneList<Expression*>(0), last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002729 }
2730 return result;
2731}
2732
2733
2734Expression* Parser::ParseNewExpression(bool* ok) {
2735 PositionStack stack(ok);
2736 return ParseNewPrefix(&stack, ok);
2737}
2738
2739
2740Expression* Parser::ParseMemberExpression(bool* ok) {
2741 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2742}
2743
2744
2745Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2746 bool* ok) {
2747 // MemberExpression ::
2748 // (PrimaryExpression | FunctionLiteral)
2749 // ('[' Expression ']' | '.' Identifier | Arguments)*
2750
2751 // Parse the initial primary or function expression.
2752 Expression* result = NULL;
2753 if (peek() == Token::FUNCTION) {
2754 Expect(Token::FUNCTION, CHECK_OK);
2755 int function_token_position = scanner().location().beg_pos;
2756 Handle<String> name;
Steve Block1e0659c2011-05-24 12:43:12 +01002757 bool is_reserved_name = false;
2758 if (peek_any_identifier()) {
2759 name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK);
2760 }
2761 result = ParseFunctionLiteral(name, is_reserved_name,
2762 function_token_position, NESTED, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002763 } else {
2764 result = ParsePrimaryExpression(CHECK_OK);
2765 }
2766
2767 while (true) {
2768 switch (peek()) {
2769 case Token::LBRACK: {
2770 Consume(Token::LBRACK);
2771 int pos = scanner().location().beg_pos;
2772 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002773 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002774 Expect(Token::RBRACK, CHECK_OK);
2775 break;
2776 }
2777 case Token::PERIOD: {
2778 Consume(Token::PERIOD);
2779 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002780 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002781 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002782 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002783 break;
2784 }
2785 case Token::LPAREN: {
2786 if ((stack == NULL) || stack->is_empty()) return result;
2787 // Consume one of the new prefixes (already parsed).
2788 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2789 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002790 result = new CallNew(result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002791 break;
2792 }
2793 default:
2794 return result;
2795 }
2796 }
2797}
2798
2799
2800DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2801 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2802 // contexts this is used as a statement which invokes the debugger as i a
2803 // break point is present.
2804 // DebuggerStatement ::
2805 // 'debugger' ';'
2806
2807 Expect(Token::DEBUGGER, CHECK_OK);
2808 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002809 return new DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002810}
2811
2812
2813void Parser::ReportUnexpectedToken(Token::Value token) {
2814 // We don't report stack overflows here, to avoid increasing the
2815 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002816 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002817 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002818 // Four of the tokens are treated specially
2819 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002820 case Token::EOS:
2821 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2822 case Token::NUMBER:
2823 return ReportMessage("unexpected_token_number",
2824 Vector<const char*>::empty());
2825 case Token::STRING:
2826 return ReportMessage("unexpected_token_string",
2827 Vector<const char*>::empty());
2828 case Token::IDENTIFIER:
2829 return ReportMessage("unexpected_token_identifier",
2830 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002831 case Token::FUTURE_RESERVED_WORD:
2832 return ReportMessage(temp_scope_->StrictMode() ?
2833 "unexpected_strict_reserved" :
2834 "unexpected_token_identifier",
2835 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002836 default:
2837 const char* name = Token::String(token);
2838 ASSERT(name != NULL);
2839 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002840 }
2841}
2842
2843
Leon Clarkeac952652010-07-15 11:15:24 +01002844void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2845 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2846 const char* element[1] = { *name_string };
2847 ReportMessage("invalid_preparser_data",
2848 Vector<const char*>(element, 1));
2849 *ok = false;
2850}
2851
2852
Steve Blocka7e24c12009-10-30 11:49:00 +00002853Expression* Parser::ParsePrimaryExpression(bool* ok) {
2854 // PrimaryExpression ::
2855 // 'this'
2856 // 'null'
2857 // 'true'
2858 // 'false'
2859 // Identifier
2860 // Number
2861 // String
2862 // ArrayLiteral
2863 // ObjectLiteral
2864 // RegExpLiteral
2865 // '(' Expression ')'
2866
2867 Expression* result = NULL;
2868 switch (peek()) {
2869 case Token::THIS: {
2870 Consume(Token::THIS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002871 VariableProxy* recv = top_scope_->receiver();
2872 result = recv;
Steve Blocka7e24c12009-10-30 11:49:00 +00002873 break;
2874 }
2875
2876 case Token::NULL_LITERAL:
2877 Consume(Token::NULL_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002878 result = new Literal(Factory::null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002879 break;
2880
2881 case Token::TRUE_LITERAL:
2882 Consume(Token::TRUE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002883 result = new Literal(Factory::true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002884 break;
2885
2886 case Token::FALSE_LITERAL:
2887 Consume(Token::FALSE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002888 result = new Literal(Factory::false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002889 break;
2890
Steve Block1e0659c2011-05-24 12:43:12 +01002891 case Token::IDENTIFIER:
2892 case Token::FUTURE_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00002893 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002894 if (fni_ != NULL) fni_->PushVariableName(name);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002895 result = top_scope_->NewUnresolved(name, inside_with());
Steve Blocka7e24c12009-10-30 11:49:00 +00002896 break;
2897 }
2898
2899 case Token::NUMBER: {
2900 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01002901 ASSERT(scanner().is_literal_ascii());
2902 double value = StringToDouble(scanner().literal_ascii_string(),
2903 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002904 result = NewNumberLiteral(value);
2905 break;
2906 }
2907
2908 case Token::STRING: {
2909 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01002910 Handle<String> symbol = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002911 result = new Literal(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002912 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002913 break;
2914 }
2915
2916 case Token::ASSIGN_DIV:
2917 result = ParseRegExpLiteral(true, CHECK_OK);
2918 break;
2919
2920 case Token::DIV:
2921 result = ParseRegExpLiteral(false, CHECK_OK);
2922 break;
2923
2924 case Token::LBRACK:
2925 result = ParseArrayLiteral(CHECK_OK);
2926 break;
2927
2928 case Token::LBRACE:
2929 result = ParseObjectLiteral(CHECK_OK);
2930 break;
2931
2932 case Token::LPAREN:
2933 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002934 // Heuristically try to detect immediately called functions before
2935 // seeing the call parentheses.
2936 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00002937 result = ParseExpression(true, CHECK_OK);
2938 Expect(Token::RPAREN, CHECK_OK);
2939 break;
2940
2941 case Token::MOD:
2942 if (allow_natives_syntax_ || extension_ != NULL) {
2943 result = ParseV8Intrinsic(CHECK_OK);
2944 break;
2945 }
2946 // If we're not allowing special syntax we fall-through to the
2947 // default case.
2948
2949 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01002950 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00002951 ReportUnexpectedToken(tok);
2952 *ok = false;
2953 return NULL;
2954 }
2955 }
2956
2957 return result;
2958}
2959
2960
Leon Clarke4515c472010-02-03 11:58:03 +00002961void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
2962 Handle<FixedArray> literals,
2963 bool* is_simple,
2964 int* depth) {
2965 // Fill in the literals.
2966 // Accumulate output values in local variables.
2967 bool is_simple_acc = true;
2968 int depth_acc = 1;
2969 for (int i = 0; i < values->length(); i++) {
2970 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
2971 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2972 depth_acc = m_literal->depth() + 1;
2973 }
2974 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
2975 if (boilerplate_value->IsUndefined()) {
2976 literals->set_the_hole(i);
2977 is_simple_acc = false;
2978 } else {
2979 literals->set(i, *boilerplate_value);
2980 }
2981 }
2982
2983 *is_simple = is_simple_acc;
2984 *depth = depth_acc;
2985}
2986
2987
Steve Blocka7e24c12009-10-30 11:49:00 +00002988Expression* Parser::ParseArrayLiteral(bool* ok) {
2989 // ArrayLiteral ::
2990 // '[' Expression? (',' Expression?)* ']'
2991
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002992 ZoneList<Expression*>* values = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002993 Expect(Token::LBRACK, CHECK_OK);
2994 while (peek() != Token::RBRACK) {
2995 Expression* elem;
2996 if (peek() == Token::COMMA) {
2997 elem = GetLiteralTheHole();
2998 } else {
2999 elem = ParseAssignmentExpression(true, CHECK_OK);
3000 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003001 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00003002 if (peek() != Token::RBRACK) {
3003 Expect(Token::COMMA, CHECK_OK);
3004 }
3005 }
3006 Expect(Token::RBRACK, CHECK_OK);
3007
3008 // Update the scope information before the pre-parsing bailout.
Steve Blocka7e24c12009-10-30 11:49:00 +00003009 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
3010
Steve Blocka7e24c12009-10-30 11:49:00 +00003011 // Allocate a fixed array with all the literals.
3012 Handle<FixedArray> literals =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003013 Factory::NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003014
3015 // Fill in the literals.
3016 bool is_simple = true;
3017 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003018 for (int i = 0, n = values->length(); i < n; i++) {
3019 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003020 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3021 depth = m_literal->depth() + 1;
3022 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003023 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003024 if (boilerplate_value->IsUndefined()) {
3025 literals->set_the_hole(i);
3026 is_simple = false;
3027 } else {
3028 literals->set(i, *boilerplate_value);
3029 }
3030 }
3031
Iain Merrick75681382010-08-19 15:07:18 +01003032 // Simple and shallow arrays can be lazily copied, we transform the
3033 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003034 if (is_simple && depth == 1 && values->length() > 0) {
Iain Merrick75681382010-08-19 15:07:18 +01003035 literals->set_map(Heap::fixed_cow_array_map());
3036 }
3037
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003038 return new ArrayLiteral(literals, values,
3039 literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003040}
3041
3042
3043bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3044 return property != NULL &&
3045 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3046}
3047
3048
3049bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003050 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003051 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3052 return lit != NULL && lit->is_simple();
3053}
3054
Iain Merrick75681382010-08-19 15:07:18 +01003055
3056bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3057 Expression* value) {
3058 // If value is a literal the property value is already set in the
3059 // boilerplate object.
3060 if (value->AsLiteral() != NULL) return false;
3061 // If value is a materialized literal the property value is already set
3062 // in the boilerplate object if it is simple.
3063 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3064 return true;
3065}
3066
3067
Steve Blocka7e24c12009-10-30 11:49:00 +00003068Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3069 ASSERT(IsCompileTimeValue(expression));
3070 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
3071 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3072 if (object_literal != NULL) {
3073 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003074 if (object_literal->fast_elements()) {
3075 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3076 } else {
3077 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3078 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003079 result->set(kElementsSlot, *object_literal->constant_properties());
3080 } else {
3081 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3082 ASSERT(array_literal != NULL && array_literal->is_simple());
3083 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003084 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003085 }
3086 return result;
3087}
3088
3089
3090CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3091 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3092 return static_cast<Type>(type_value->value());
3093}
3094
3095
3096Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3097 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3098}
3099
3100
3101Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3102 if (expression->AsLiteral() != NULL) {
3103 return expression->AsLiteral()->handle();
3104 }
3105 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3106 return CompileTimeValue::GetValue(expression);
3107 }
3108 return Factory::undefined_value();
3109}
3110
Steve Block1e0659c2011-05-24 12:43:12 +01003111// Defined in ast.cc
3112bool IsEqualString(void* first, void* second);
3113bool IsEqualNumber(void* first, void* second);
3114
3115
3116// Validation per 11.1.5 Object Initialiser
3117class ObjectLiteralPropertyChecker {
3118 public:
3119 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3120 props(&IsEqualString),
3121 elems(&IsEqualNumber),
3122 parser_(parser),
3123 strict_(strict) {
3124 }
3125
3126 void CheckProperty(
3127 ObjectLiteral::Property* property,
3128 Scanner::Location loc,
3129 bool* ok);
3130
3131 private:
3132 enum PropertyKind {
3133 kGetAccessor = 0x01,
3134 kSetAccessor = 0x02,
3135 kAccessor = kGetAccessor | kSetAccessor,
3136 kData = 0x04
3137 };
3138
3139 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3140 switch (property->kind()) {
3141 case ObjectLiteral::Property::GETTER:
3142 return kGetAccessor;
3143 case ObjectLiteral::Property::SETTER:
3144 return kSetAccessor;
3145 default:
3146 return kData;
3147 }
3148 }
3149
3150 HashMap props;
3151 HashMap elems;
3152 Parser* parser_;
3153 bool strict_;
3154};
3155
3156
3157void ObjectLiteralPropertyChecker::CheckProperty(
3158 ObjectLiteral::Property* property,
3159 Scanner::Location loc,
3160 bool* ok) {
3161
3162 ASSERT(property != NULL);
3163
3164 Literal *lit = property->key();
3165 Handle<Object> handle = lit->handle();
3166
3167 uint32_t hash;
3168 HashMap* map;
3169 void* key;
3170
3171 if (handle->IsSymbol()) {
3172 Handle<String> name(String::cast(*handle));
3173 if (name->AsArrayIndex(&hash)) {
3174 Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
3175 key = key_handle.location();
3176 map = &elems;
3177 } else {
3178 key = handle.location();
3179 hash = name->Hash();
3180 map = &props;
3181 }
3182 } else if (handle->ToArrayIndex(&hash)) {
3183 key = handle.location();
3184 map = &elems;
3185 } else {
3186 ASSERT(handle->IsNumber());
3187 double num = handle->Number();
3188 char arr[100];
3189 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3190 const char* str = DoubleToCString(num, buffer);
3191 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
3192 key = name.location();
3193 hash = name->Hash();
3194 map = &props;
3195 }
3196
3197 // Lookup property previously defined, if any.
3198 HashMap::Entry* entry = map->Lookup(key, hash, true);
3199 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3200 intptr_t curr = GetPropertyKind(property);
3201
3202 // Duplicate data properties are illegal in strict mode.
3203 if (strict_ && (curr & prev & kData) != 0) {
3204 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3205 Vector<const char*>::empty());
3206 *ok = false;
3207 return;
3208 }
3209 // Data property conflicting with an accessor.
3210 if (((curr & kData) && (prev & kAccessor)) ||
3211 ((prev & kData) && (curr & kAccessor))) {
3212 parser_->ReportMessageAt(loc, "accessor_data_property",
3213 Vector<const char*>::empty());
3214 *ok = false;
3215 return;
3216 }
3217 // Two accessors of the same type conflicting
3218 if ((curr & prev & kAccessor) != 0) {
3219 parser_->ReportMessageAt(loc, "accessor_get_set",
3220 Vector<const char*>::empty());
3221 *ok = false;
3222 return;
3223 }
3224
3225 // Update map
3226 entry->value = reinterpret_cast<void*> (prev | curr);
3227 *ok = true;
3228}
3229
Steve Blocka7e24c12009-10-30 11:49:00 +00003230
Leon Clarke4515c472010-02-03 11:58:03 +00003231void Parser::BuildObjectLiteralConstantProperties(
3232 ZoneList<ObjectLiteral::Property*>* properties,
3233 Handle<FixedArray> constant_properties,
3234 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003235 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003236 int* depth) {
3237 int position = 0;
3238 // Accumulate the value in local variables and store it at the end.
3239 bool is_simple_acc = true;
3240 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003241 uint32_t max_element_index = 0;
3242 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003243 for (int i = 0; i < properties->length(); i++) {
3244 ObjectLiteral::Property* property = properties->at(i);
3245 if (!IsBoilerplateProperty(property)) {
3246 is_simple_acc = false;
3247 continue;
3248 }
3249 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3250 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3251 depth_acc = m_literal->depth() + 1;
3252 }
3253
3254 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3255 // value for COMPUTED properties, the real value is filled in at
3256 // runtime. The enumeration order is maintained.
3257 Handle<Object> key = property->key()->handle();
3258 Handle<Object> value = GetBoilerplateValue(property->value());
3259 is_simple_acc = is_simple_acc && !value->IsUndefined();
3260
Steve Block6ded16b2010-05-10 14:33:55 +01003261 // Keep track of the number of elements in the object literal and
3262 // the largest element index. If the largest element index is
3263 // much larger than the number of elements, creating an object
3264 // literal with fast elements will be a waste of space.
3265 uint32_t element_index = 0;
3266 if (key->IsString()
3267 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3268 && element_index > max_element_index) {
3269 max_element_index = element_index;
3270 elements++;
3271 } else if (key->IsSmi()) {
3272 int key_value = Smi::cast(*key)->value();
3273 if (key_value > 0
3274 && static_cast<uint32_t>(key_value) > max_element_index) {
3275 max_element_index = key_value;
3276 }
3277 elements++;
3278 }
3279
Leon Clarke4515c472010-02-03 11:58:03 +00003280 // Add name, value pair to the fixed array.
3281 constant_properties->set(position++, *key);
3282 constant_properties->set(position++, *value);
3283 }
Steve Block6ded16b2010-05-10 14:33:55 +01003284 *fast_elements =
3285 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003286 *is_simple = is_simple_acc;
3287 *depth = depth_acc;
3288}
3289
3290
Ben Murdochbb769b22010-08-11 14:56:33 +01003291ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3292 bool* ok) {
3293 // Special handling of getter and setter syntax:
3294 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3295 // We have already read the "get" or "set" keyword.
3296 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003297 bool is_keyword = Token::IsKeyword(next);
3298 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003299 next == Token::FUTURE_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003300 next == Token::STRING || is_keyword) {
3301 Handle<String> name;
3302 if (is_keyword) {
3303 name = Factory::LookupAsciiSymbol(Token::String(next));
3304 } else {
3305 name = GetSymbol(CHECK_OK);
3306 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003307 FunctionLiteral* value =
3308 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003309 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003310 RelocInfo::kNoPosition,
3311 DECLARATION,
3312 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003313 // Allow any number of parameters for compatiabilty with JSC.
3314 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003315 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003316 new ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003317 return property;
3318 } else {
3319 ReportUnexpectedToken(next);
3320 *ok = false;
3321 return NULL;
3322 }
3323}
3324
3325
Steve Blocka7e24c12009-10-30 11:49:00 +00003326Expression* Parser::ParseObjectLiteral(bool* ok) {
3327 // ObjectLiteral ::
3328 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003329 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3330 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003331 // )*[','] '}'
3332
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003333 ZoneList<ObjectLiteral::Property*>* properties =
3334 new ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003335 int number_of_boilerplate_properties = 0;
3336
Steve Block1e0659c2011-05-24 12:43:12 +01003337 ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode());
3338
Steve Blocka7e24c12009-10-30 11:49:00 +00003339 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003340 Scanner::Location loc = scanner().location();
3341
Steve Blocka7e24c12009-10-30 11:49:00 +00003342 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003343 if (fni_ != NULL) fni_->Enter();
3344
Steve Blocka7e24c12009-10-30 11:49:00 +00003345 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003346 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003347
3348 // Location of the property name token
3349 Scanner::Location loc = scanner().peek_location();
3350
Ben Murdochbb769b22010-08-11 14:56:33 +01003351 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003352 case Token::FUTURE_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003353 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003354 bool is_getter = false;
3355 bool is_setter = false;
3356 Handle<String> id =
3357 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003358 if (fni_ != NULL) fni_->PushLiteralName(id);
3359
Ben Murdochbb769b22010-08-11 14:56:33 +01003360 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003361 // Update loc to point to the identifier
3362 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003363 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003364 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3365 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003366 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003367 }
Steve Block1e0659c2011-05-24 12:43:12 +01003368 // Validate the property.
3369 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003370 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003371 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003372
3373 if (fni_ != NULL) {
3374 fni_->Infer();
3375 fni_->Leave();
3376 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003377 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003378 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003379 // Failed to parse as get/set property, so it's just a property
3380 // called "get" or "set".
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003381 key = new Literal(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003382 break;
3383 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003384 case Token::STRING: {
3385 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003386 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003387 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003388 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003389 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003390 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003391 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003392 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003393 key = new Literal(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003394 break;
3395 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003396 case Token::NUMBER: {
3397 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003398 ASSERT(scanner().is_literal_ascii());
3399 double value = StringToDouble(scanner().literal_ascii_string(),
3400 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003401 key = NewNumberLiteral(value);
3402 break;
3403 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003404 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003405 if (Token::IsKeyword(next)) {
3406 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003407 Handle<String> string = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003408 key = new Literal(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003409 } else {
3410 // Unexpected token.
3411 Token::Value next = Next();
3412 ReportUnexpectedToken(next);
3413 *ok = false;
3414 return NULL;
3415 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003416 }
3417
3418 Expect(Token::COLON, CHECK_OK);
3419 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3420
3421 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003422 new ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003423
3424 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3425 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003426 // Validate the property
3427 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003428 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003429
3430 // TODO(1240767): Consider allowing trailing comma.
3431 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003432
3433 if (fni_ != NULL) {
3434 fni_->Infer();
3435 fni_->Leave();
3436 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003437 }
3438 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003439
Steve Blocka7e24c12009-10-30 11:49:00 +00003440 // Computation of literal_index must happen before pre parse bailout.
3441 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003442
3443 Handle<FixedArray> constant_properties =
3444 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003445
Steve Blocka7e24c12009-10-30 11:49:00 +00003446 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003447 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003448 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003449 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003450 constant_properties,
3451 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003452 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003453 &depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003454 return new ObjectLiteral(constant_properties,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003455 properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003456 literal_index,
3457 is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003458 fast_elements,
Steve Blocka7e24c12009-10-30 11:49:00 +00003459 depth);
3460}
3461
3462
3463Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003464 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003465 Next();
3466 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3467 *ok = false;
3468 return NULL;
3469 }
3470
3471 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
3472
Steve Block9fac8402011-05-12 15:51:54 +01003473 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003474 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003475 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003476 Next();
3477
3478 return new RegExpLiteral(js_pattern, js_flags, literal_index);
3479}
3480
3481
3482ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3483 // Arguments ::
3484 // '(' (AssignmentExpression)*[','] ')'
3485
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003486 ZoneList<Expression*>* result = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003487 Expect(Token::LPAREN, CHECK_OK);
3488 bool done = (peek() == Token::RPAREN);
3489 while (!done) {
3490 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003491 result->Add(argument);
Steve Blocka7e24c12009-10-30 11:49:00 +00003492 done = (peek() == Token::RPAREN);
3493 if (!done) Expect(Token::COMMA, CHECK_OK);
3494 }
3495 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003496 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003497}
3498
3499
3500FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
Steve Block1e0659c2011-05-24 12:43:12 +01003501 bool name_is_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003502 int function_token_position,
3503 FunctionLiteralType type,
3504 bool* ok) {
3505 // Function ::
3506 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003507 bool is_named = !var_name.is_null();
3508
3509 // The name associated with this function. If it's a function expression,
3510 // this is the actual function name, otherwise this is the name of the
3511 // variable declared and initialized with the function (expression). In
3512 // that case, we don't have a function name (it's empty).
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003513 Handle<String> name = is_named ? var_name : Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003514 // The function name, if any.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003515 Handle<String> function_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003516 if (is_named && (type == EXPRESSION || type == NESTED)) {
3517 function_name = name;
3518 }
3519
3520 int num_parameters = 0;
3521 // Parse function body.
Ben Murdochf87a2032010-10-22 12:50:53 +01003522 { Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003523 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3524 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
3525 scope);
3526 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003527 top_scope_->SetScopeName(name);
3528
3529 // FormalParameterList ::
3530 // '(' (Identifier)*[','] ')'
3531 Expect(Token::LPAREN, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003532 int start_pos = scanner().location().beg_pos;
Steve Block1e0659c2011-05-24 12:43:12 +01003533 Scanner::Location name_loc = Scanner::NoLocation();
3534 Scanner::Location dupe_loc = Scanner::NoLocation();
3535 Scanner::Location reserved_loc = Scanner::NoLocation();
3536
Steve Blocka7e24c12009-10-30 11:49:00 +00003537 bool done = (peek() == Token::RPAREN);
3538 while (!done) {
Steve Block1e0659c2011-05-24 12:43:12 +01003539 bool is_reserved = false;
3540 Handle<String> param_name =
3541 ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK);
3542
3543 // Store locations for possible future error reports.
3544 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3545 name_loc = scanner().location();
3546 }
3547 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
3548 dupe_loc = scanner().location();
3549 }
3550 if (!reserved_loc.IsValid() && is_reserved) {
3551 reserved_loc = scanner().location();
3552 }
3553
3554 Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR);
3555 top_scope_->AddParameter(parameter);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003556 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003557 if (num_parameters > kMaxNumFunctionParameters) {
3558 ReportMessageAt(scanner().location(), "too_many_parameters",
3559 Vector<const char*>::empty());
3560 *ok = false;
3561 return NULL;
3562 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003563 done = (peek() == Token::RPAREN);
3564 if (!done) Expect(Token::COMMA, CHECK_OK);
3565 }
3566 Expect(Token::RPAREN, CHECK_OK);
3567
3568 Expect(Token::LBRACE, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003569 ZoneList<Statement*>* body = new ZoneList<Statement*>(8);
Steve Blocka7e24c12009-10-30 11:49:00 +00003570
3571 // If we have a named function expression, we add a local variable
3572 // declaration to the body of the function with the name of the
3573 // function and let it refer to the function itself (closure).
3574 // NOTE: We create a proxy and resolve it here so that in the
3575 // future we can change the AST to only refer to VariableProxies
3576 // instead of Variables and Proxis as is the case now.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003577 if (!function_name.is_null() && function_name->length() > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003578 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3579 VariableProxy* fproxy =
3580 top_scope_->NewUnresolved(function_name, inside_with());
3581 fproxy->BindTo(fvar);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003582 body->Add(new ExpressionStatement(
3583 new Assignment(Token::INIT_CONST, fproxy,
3584 new ThisFunction(),
3585 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003586 }
3587
3588 // Determine if the function will be lazily compiled. The mode can
3589 // only be PARSE_LAZILY if the --lazy flag is true.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003590 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3591 top_scope_->outer_scope()->is_global_scope() &&
3592 top_scope_->HasTrivialOuterContext() &&
3593 !parenthesized_function_);
3594 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003595
Ben Murdochb0fe1622011-05-05 13:52:32 +01003596 int function_block_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003597 int materialized_literal_count;
3598 int expected_property_count;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003599 int end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003600 bool only_simple_this_property_assignments;
3601 Handle<FixedArray> this_property_assignments;
3602 if (is_lazily_compiled && pre_data() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003603 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003604 if (!entry.is_valid()) {
3605 ReportInvalidPreparseData(name, CHECK_OK);
3606 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003607 end_pos = entry.end_pos();
3608 if (end_pos <= function_block_pos) {
Leon Clarkeac952652010-07-15 11:15:24 +01003609 // End position greater than end of stream is safe, and hard to check.
3610 ReportInvalidPreparseData(name, CHECK_OK);
3611 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003612 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003613 // Seek to position just before terminal '}'.
3614 scanner().SeekForward(end_pos - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003615 materialized_literal_count = entry.literal_count();
3616 expected_property_count = entry.property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003617 only_simple_this_property_assignments = false;
3618 this_property_assignments = Factory::empty_fixed_array();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003619 Expect(Token::RBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003620 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003621 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3622
Steve Blocka7e24c12009-10-30 11:49:00 +00003623 materialized_literal_count = temp_scope.materialized_literal_count();
3624 expected_property_count = temp_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003625 only_simple_this_property_assignments =
3626 temp_scope.only_simple_this_property_assignments();
3627 this_property_assignments = temp_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003628
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003629 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003630 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003631 }
3632
Steve Block1e0659c2011-05-24 12:43:12 +01003633 // Validate strict mode.
3634 if (temp_scope_->StrictMode()) {
3635 if (IsEvalOrArguments(name)) {
3636 int position = function_token_position != RelocInfo::kNoPosition
3637 ? function_token_position
3638 : (start_pos > 0 ? start_pos - 1 : start_pos);
3639 Scanner::Location location = Scanner::Location(position, start_pos);
3640 ReportMessageAt(location,
3641 "strict_function_name", Vector<const char*>::empty());
3642 *ok = false;
3643 return NULL;
3644 }
3645 if (name_loc.IsValid()) {
3646 ReportMessageAt(name_loc, "strict_param_name",
3647 Vector<const char*>::empty());
3648 *ok = false;
3649 return NULL;
3650 }
3651 if (dupe_loc.IsValid()) {
3652 ReportMessageAt(dupe_loc, "strict_param_dupe",
3653 Vector<const char*>::empty());
3654 *ok = false;
3655 return NULL;
3656 }
3657 if (name_is_reserved) {
3658 int position = function_token_position != RelocInfo::kNoPosition
3659 ? function_token_position
3660 : (start_pos > 0 ? start_pos - 1 : start_pos);
3661 Scanner::Location location = Scanner::Location(position, start_pos);
3662 ReportMessageAt(location, "strict_reserved_word",
3663 Vector<const char*>::empty());
3664 *ok = false;
3665 return NULL;
3666 }
3667 if (reserved_loc.IsValid()) {
3668 ReportMessageAt(reserved_loc, "strict_reserved_word",
3669 Vector<const char*>::empty());
3670 *ok = false;
3671 return NULL;
3672 }
3673 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3674 }
3675
Steve Blocka7e24c12009-10-30 11:49:00 +00003676 FunctionLiteral* function_literal =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003677 new FunctionLiteral(name,
Steve Blocka7e24c12009-10-30 11:49:00 +00003678 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003679 body,
Steve Blocka7e24c12009-10-30 11:49:00 +00003680 materialized_literal_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 expected_property_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003682 only_simple_this_property_assignments,
3683 this_property_assignments,
3684 num_parameters,
3685 start_pos,
3686 end_pos,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003687 function_name->length() > 0,
Steve Block1e0659c2011-05-24 12:43:12 +01003688 temp_scope.ContainsLoops(),
3689 temp_scope.StrictMode());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003690 function_literal->set_function_token_position(function_token_position);
Steve Block6ded16b2010-05-10 14:33:55 +01003691
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003692 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
Steve Blocka7e24c12009-10-30 11:49:00 +00003693 return function_literal;
3694 }
3695}
3696
3697
3698Expression* Parser::ParseV8Intrinsic(bool* ok) {
3699 // CallRuntime ::
3700 // '%' Identifier Arguments
3701
3702 Expect(Token::MOD, CHECK_OK);
3703 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003704 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003705
3706 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003707 // The extension structures are only accessible while parsing the
3708 // very first time not when reparsing because of lazy compilation.
3709 top_scope_->ForceEagerCompilation();
3710 }
3711
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003712 Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003713
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003714 // Check for built-in IS_VAR macro.
3715 if (function != NULL &&
3716 function->intrinsic_type == Runtime::RUNTIME &&
3717 function->function_id == Runtime::kIS_VAR) {
3718 // %IS_VAR(x) evaluates to x if x is a variable,
3719 // leads to a parse error otherwise. Could be implemented as an
3720 // inline function %_IS_VAR(x) to eliminate this special case.
3721 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3722 return args->at(0);
3723 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003724 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003725 *ok = false;
3726 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003727 }
3728 }
3729
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003730 // Check that the expected number of arguments are being passed.
3731 if (function != NULL &&
3732 function->nargs != -1 &&
3733 function->nargs != args->length()) {
3734 ReportMessage("illegal_access", Vector<const char*>::empty());
3735 *ok = false;
3736 return NULL;
3737 }
3738
3739 // We have a valid intrinsics call or a call to a builtin.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003740 return new CallRuntime(name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003741}
3742
3743
Steve Block1e0659c2011-05-24 12:43:12 +01003744bool Parser::peek_any_identifier() {
3745 Token::Value next = peek();
3746 return next == Token::IDENTIFIER ||
3747 next == Token::FUTURE_RESERVED_WORD;
3748}
3749
3750
Steve Blocka7e24c12009-10-30 11:49:00 +00003751void Parser::Consume(Token::Value token) {
3752 Token::Value next = Next();
3753 USE(next);
3754 USE(token);
3755 ASSERT(next == token);
3756}
3757
3758
3759void Parser::Expect(Token::Value token, bool* ok) {
3760 Token::Value next = Next();
3761 if (next == token) return;
3762 ReportUnexpectedToken(next);
3763 *ok = false;
3764}
3765
3766
Leon Clarke4515c472010-02-03 11:58:03 +00003767bool Parser::Check(Token::Value token) {
3768 Token::Value next = peek();
3769 if (next == token) {
3770 Consume(next);
3771 return true;
3772 }
3773 return false;
3774}
3775
3776
Steve Blocka7e24c12009-10-30 11:49:00 +00003777void Parser::ExpectSemicolon(bool* ok) {
3778 // Check for automatic semicolon insertion according to
3779 // the rules given in ECMA-262, section 7.9, page 21.
3780 Token::Value tok = peek();
3781 if (tok == Token::SEMICOLON) {
3782 Next();
3783 return;
3784 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003785 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003786 tok == Token::RBRACE ||
3787 tok == Token::EOS) {
3788 return;
3789 }
3790 Expect(Token::SEMICOLON, ok);
3791}
3792
3793
3794Literal* Parser::GetLiteralUndefined() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003795 return new Literal(Factory::undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003796}
3797
3798
3799Literal* Parser::GetLiteralTheHole() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003800 return new Literal(Factory::the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003801}
3802
3803
3804Literal* Parser::GetLiteralNumber(double value) {
3805 return NewNumberLiteral(value);
3806}
3807
3808
3809Handle<String> Parser::ParseIdentifier(bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003810 bool is_reserved;
3811 return ParseIdentifierOrReservedWord(&is_reserved, ok);
3812}
3813
3814
3815Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved,
3816 bool* ok) {
3817 *is_reserved = false;
3818 if (temp_scope_->StrictMode()) {
3819 Expect(Token::IDENTIFIER, ok);
3820 } else {
3821 if (!Check(Token::IDENTIFIER)) {
3822 Expect(Token::FUTURE_RESERVED_WORD, ok);
3823 *is_reserved = true;
3824 }
3825 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003826 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003827 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003828}
3829
Ben Murdochbb769b22010-08-11 14:56:33 +01003830
3831Handle<String> Parser::ParseIdentifierName(bool* ok) {
3832 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01003833 if (next != Token::IDENTIFIER &&
3834 next != Token::FUTURE_RESERVED_WORD &&
3835 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01003836 ReportUnexpectedToken(next);
3837 *ok = false;
3838 return Handle<String>();
3839 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003840 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01003841}
3842
3843
Steve Block1e0659c2011-05-24 12:43:12 +01003844// Checks LHS expression for assignment and prefix/postfix increment/decrement
3845// in strict mode.
3846void Parser::CheckStrictModeLValue(Expression* expression,
3847 const char* error,
3848 bool* ok) {
3849 ASSERT(temp_scope_->StrictMode());
3850 VariableProxy* lhs = expression != NULL
3851 ? expression->AsVariableProxy()
3852 : NULL;
3853
3854 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
3855 ReportMessage(error, Vector<const char*>::empty());
3856 *ok = false;
3857 }
3858}
3859
3860
3861// Checks whether octal literal last seen is between beg_pos and end_pos.
3862// If so, reports an error.
3863void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
3864 int octal = scanner().octal_position();
3865 if (beg_pos <= octal && octal <= end_pos) {
3866 ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal",
3867 Vector<const char*>::empty());
3868 scanner().clear_octal_position();
3869 *ok = false;
3870 }
3871}
3872
3873
Steve Blocka7e24c12009-10-30 11:49:00 +00003874// This function reads an identifier and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01003875// is 'get' or 'set'.
Steve Blocka7e24c12009-10-30 11:49:00 +00003876Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3877 bool* is_set,
3878 bool* ok) {
Steve Block1e0659c2011-05-24 12:43:12 +01003879 Handle<String> result = ParseIdentifier(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003880 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01003881 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
3882 const char* token = scanner().literal_ascii_string().start();
3883 *is_get = strncmp(token, "get", 3) == 0;
3884 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003885 }
Steve Block1e0659c2011-05-24 12:43:12 +01003886 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003887}
3888
3889
3890// ----------------------------------------------------------------------------
3891// Parser support
3892
3893
3894bool Parser::TargetStackContainsLabel(Handle<String> label) {
3895 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3896 BreakableStatement* stat = t->node()->AsBreakableStatement();
3897 if (stat != NULL && ContainsLabel(stat->labels(), label))
3898 return true;
3899 }
3900 return false;
3901}
3902
3903
3904BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3905 bool anonymous = label.is_null();
3906 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3907 BreakableStatement* stat = t->node()->AsBreakableStatement();
3908 if (stat == NULL) continue;
3909 if ((anonymous && stat->is_target_for_anonymous()) ||
3910 (!anonymous && ContainsLabel(stat->labels(), label))) {
3911 RegisterTargetUse(stat->break_target(), t->previous());
3912 return stat;
3913 }
3914 }
3915 return NULL;
3916}
3917
3918
3919IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3920 bool* ok) {
3921 bool anonymous = label.is_null();
3922 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3923 IterationStatement* stat = t->node()->AsIterationStatement();
3924 if (stat == NULL) continue;
3925
3926 ASSERT(stat->is_target_for_anonymous());
3927 if (anonymous || ContainsLabel(stat->labels(), label)) {
3928 RegisterTargetUse(stat->continue_target(), t->previous());
3929 return stat;
3930 }
3931 }
3932 return NULL;
3933}
3934
3935
3936void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) {
3937 // Register that a break target found at the given stop in the
3938 // target stack has been used from the top of the target stack. Add
3939 // the break target to any TargetCollectors passed on the stack.
3940 for (Target* t = target_stack_; t != stop; t = t->previous()) {
3941 TargetCollector* collector = t->node()->AsTargetCollector();
3942 if (collector != NULL) collector->AddTarget(target);
3943 }
3944}
3945
3946
3947Literal* Parser::NewNumberLiteral(double number) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003948 return new Literal(Factory::NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00003949}
3950
3951
3952Expression* Parser::NewThrowReferenceError(Handle<String> type) {
3953 return NewThrowError(Factory::MakeReferenceError_symbol(),
3954 type, HandleVector<Object>(NULL, 0));
3955}
3956
3957
3958Expression* Parser::NewThrowSyntaxError(Handle<String> type,
3959 Handle<Object> first) {
3960 int argc = first.is_null() ? 0 : 1;
3961 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
3962 return NewThrowError(Factory::MakeSyntaxError_symbol(), type, arguments);
3963}
3964
3965
3966Expression* Parser::NewThrowTypeError(Handle<String> type,
3967 Handle<Object> first,
3968 Handle<Object> second) {
3969 ASSERT(!first.is_null() && !second.is_null());
3970 Handle<Object> elements[] = { first, second };
3971 Vector< Handle<Object> > arguments =
3972 HandleVector<Object>(elements, ARRAY_SIZE(elements));
3973 return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments);
3974}
3975
3976
3977Expression* Parser::NewThrowError(Handle<String> constructor,
3978 Handle<String> type,
3979 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003980 int argc = arguments.length();
Steve Block1e0659c2011-05-24 12:43:12 +01003981 Handle<FixedArray> elements = Factory::NewFixedArray(argc, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003982 for (int i = 0; i < argc; i++) {
3983 Handle<Object> element = arguments[i];
3984 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003985 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00003986 }
3987 }
Steve Block1e0659c2011-05-24 12:43:12 +01003988 Handle<JSArray> array = Factory::NewJSArrayWithElements(elements, TENURED);
3989
Steve Blocka7e24c12009-10-30 11:49:00 +00003990 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
3991 args->Add(new Literal(type));
3992 args->Add(new Literal(array));
3993 return new Throw(new CallRuntime(constructor, NULL, args),
3994 scanner().location().beg_pos);
3995}
3996
Leon Clarke4515c472010-02-03 11:58:03 +00003997// ----------------------------------------------------------------------------
3998// JSON
3999
Ben Murdochb0fe1622011-05-05 13:52:32 +01004000Handle<Object> JsonParser::ParseJson(Handle<String> script,
4001 UC16CharacterStream* source) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004002 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004003 stack_overflow_ = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004004 Handle<Object> result = ParseJsonValue();
4005 if (result.is_null() || scanner_.Next() != Token::EOS) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004006 if (stack_overflow_) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004007 // Scanner failed.
4008 Top::StackOverflow();
4009 } else {
4010 // Parse failed. Scanner's current token is the unexpected token.
4011 Token::Value token = scanner_.current_token();
4012
4013 const char* message;
4014 const char* name_opt = NULL;
4015
4016 switch (token) {
4017 case Token::EOS:
4018 message = "unexpected_eos";
4019 break;
4020 case Token::NUMBER:
4021 message = "unexpected_token_number";
4022 break;
4023 case Token::STRING:
4024 message = "unexpected_token_string";
4025 break;
4026 case Token::IDENTIFIER:
Steve Block1e0659c2011-05-24 12:43:12 +01004027 case Token::FUTURE_RESERVED_WORD:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004028 message = "unexpected_token_identifier";
4029 break;
4030 default:
4031 message = "unexpected_token";
4032 name_opt = Token::String(token);
4033 ASSERT(name_opt != NULL);
4034 break;
4035 }
4036
4037 Scanner::Location source_location = scanner_.location();
Ben Murdochb0fe1622011-05-05 13:52:32 +01004038 MessageLocation location(Factory::NewScript(script),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004039 source_location.beg_pos,
4040 source_location.end_pos);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004041 Handle<JSArray> array;
4042 if (name_opt == NULL) {
4043 array = Factory::NewJSArray(0);
4044 } else {
4045 Handle<String> name = Factory::NewStringFromUtf8(CStrVector(name_opt));
4046 Handle<FixedArray> element = Factory::NewFixedArray(1);
4047 element->set(0, *name);
4048 array = Factory::NewJSArrayWithElements(element);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004049 }
4050 Handle<Object> result = Factory::NewSyntaxError(message, array);
4051 Top::Throw(*result, &location);
4052 return Handle<Object>::null();
4053 }
4054 }
Leon Clarke4515c472010-02-03 11:58:03 +00004055 return result;
4056}
4057
4058
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004059Handle<String> JsonParser::GetString() {
4060 int literal_length = scanner_.literal_length();
4061 if (literal_length == 0) {
4062 return Factory::empty_string();
4063 }
Steve Block9fac8402011-05-12 15:51:54 +01004064 if (scanner_.is_literal_ascii()) {
4065 return Factory::NewStringFromAscii(scanner_.literal_ascii_string());
4066 } else {
4067 return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string());
4068 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004069}
4070
4071
Leon Clarke4515c472010-02-03 11:58:03 +00004072// Parse any JSON value.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004073Handle<Object> JsonParser::ParseJsonValue() {
4074 Token::Value token = scanner_.Next();
Leon Clarke4515c472010-02-03 11:58:03 +00004075 switch (token) {
Steve Block1e0659c2011-05-24 12:43:12 +01004076 case Token::STRING:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004077 return GetString();
Steve Block1e0659c2011-05-24 12:43:12 +01004078 case Token::NUMBER:
4079 return Factory::NewNumber(scanner_.number());
Leon Clarke4515c472010-02-03 11:58:03 +00004080 case Token::FALSE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004081 return Factory::false_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004082 case Token::TRUE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004083 return Factory::true_value();
Leon Clarke4515c472010-02-03 11:58:03 +00004084 case Token::NULL_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004085 return Factory::null_value();
4086 case Token::LBRACE:
4087 return ParseJsonObject();
4088 case Token::LBRACK:
4089 return ParseJsonArray();
Leon Clarke4515c472010-02-03 11:58:03 +00004090 default:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004091 return ReportUnexpectedToken();
Leon Clarke4515c472010-02-03 11:58:03 +00004092 }
4093}
4094
4095
4096// Parse a JSON object. Scanner must be right after '{' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004097Handle<Object> JsonParser::ParseJsonObject() {
4098 Handle<JSFunction> object_constructor(
4099 Top::global_context()->object_function());
4100 Handle<JSObject> json_object = Factory::NewJSObject(object_constructor);
4101 if (scanner_.peek() == Token::RBRACE) {
4102 scanner_.Next();
4103 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004104 if (StackLimitCheck().HasOverflowed()) {
4105 stack_overflow_ = true;
4106 return Handle<Object>::null();
4107 }
Leon Clarke4515c472010-02-03 11:58:03 +00004108 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004109 if (scanner_.Next() != Token::STRING) {
4110 return ReportUnexpectedToken();
4111 }
4112 Handle<String> key = GetString();
4113 if (scanner_.Next() != Token::COLON) {
4114 return ReportUnexpectedToken();
4115 }
4116 Handle<Object> value = ParseJsonValue();
4117 if (value.is_null()) return Handle<Object>::null();
Leon Clarke4515c472010-02-03 11:58:03 +00004118 uint32_t index;
4119 if (key->AsArrayIndex(&index)) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004120 SetOwnElement(json_object, index, value, kNonStrictMode);
Steve Block1e0659c2011-05-24 12:43:12 +01004121 } else if (key->Equals(Heap::Proto_symbol())) {
4122 // We can't remove the __proto__ accessor since it's hardcoded
4123 // in several places. Instead go along and add the value as
4124 // the prototype of the created object if possible.
4125 SetPrototype(json_object, value);
Leon Clarke4515c472010-02-03 11:58:03 +00004126 } else {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004127 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
Leon Clarke4515c472010-02-03 11:58:03 +00004128 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004129 } while (scanner_.Next() == Token::COMMA);
4130 if (scanner_.current_token() != Token::RBRACE) {
4131 return ReportUnexpectedToken();
4132 }
Leon Clarke4515c472010-02-03 11:58:03 +00004133 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004134 return json_object;
Leon Clarke4515c472010-02-03 11:58:03 +00004135}
4136
4137
4138// Parse a JSON array. Scanner must be right after '[' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004139Handle<Object> JsonParser::ParseJsonArray() {
4140 ZoneScope zone_scope(DELETE_ON_EXIT);
4141 ZoneList<Handle<Object> > elements(4);
Leon Clarke4515c472010-02-03 11:58:03 +00004142
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004143 Token::Value token = scanner_.peek();
4144 if (token == Token::RBRACK) {
4145 scanner_.Next();
4146 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004147 if (StackLimitCheck().HasOverflowed()) {
4148 stack_overflow_ = true;
4149 return Handle<Object>::null();
4150 }
Leon Clarke4515c472010-02-03 11:58:03 +00004151 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004152 Handle<Object> element = ParseJsonValue();
4153 if (element.is_null()) return Handle<Object>::null();
4154 elements.Add(element);
4155 token = scanner_.Next();
4156 } while (token == Token::COMMA);
4157 if (token != Token::RBRACK) {
4158 return ReportUnexpectedToken();
4159 }
Leon Clarke4515c472010-02-03 11:58:03 +00004160 }
Leon Clarke4515c472010-02-03 11:58:03 +00004161
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004162 // Allocate a fixed array with all the elements.
4163 Handle<FixedArray> fast_elements =
4164 Factory::NewFixedArray(elements.length());
Leon Clarke4515c472010-02-03 11:58:03 +00004165
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004166 for (int i = 0, n = elements.length(); i < n; i++) {
4167 fast_elements->set(i, *elements[i]);
4168 }
Leon Clarke4515c472010-02-03 11:58:03 +00004169
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004170 return Factory::NewJSArrayWithElements(fast_elements);
Leon Clarke4515c472010-02-03 11:58:03 +00004171}
4172
Steve Blocka7e24c12009-10-30 11:49:00 +00004173// ----------------------------------------------------------------------------
4174// Regular expressions
4175
4176
4177RegExpParser::RegExpParser(FlatStringReader* in,
4178 Handle<String>* error,
4179 bool multiline)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004180 : error_(error),
4181 captures_(NULL),
4182 in_(in),
4183 current_(kEndMarker),
4184 next_pos_(0),
4185 capture_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +00004186 has_more_(true),
4187 multiline_(multiline),
Steve Blocka7e24c12009-10-30 11:49:00 +00004188 simple_(false),
4189 contains_anchor_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00004190 is_scanned_for_captures_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00004191 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004192 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004193}
4194
4195
4196uc32 RegExpParser::Next() {
4197 if (has_next()) {
4198 return in()->Get(next_pos_);
4199 } else {
4200 return kEndMarker;
4201 }
4202}
4203
4204
4205void RegExpParser::Advance() {
4206 if (next_pos_ < in()->length()) {
4207 StackLimitCheck check;
4208 if (check.HasOverflowed()) {
4209 ReportError(CStrVector(Top::kStackOverflowMessage));
4210 } else if (Zone::excess_allocation()) {
4211 ReportError(CStrVector("Regular expression too large"));
4212 } else {
4213 current_ = in()->Get(next_pos_);
4214 next_pos_++;
4215 }
4216 } else {
4217 current_ = kEndMarker;
4218 has_more_ = false;
4219 }
4220}
4221
4222
4223void RegExpParser::Reset(int pos) {
4224 next_pos_ = pos;
4225 Advance();
4226}
4227
4228
4229void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004230 next_pos_ += dist - 1;
4231 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004232}
4233
4234
4235bool RegExpParser::simple() {
4236 return simple_;
4237}
4238
4239RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4240 failed_ = true;
4241 *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
4242 // Zip to the end to make sure the no more input is read.
4243 current_ = kEndMarker;
4244 next_pos_ = in()->length();
4245 return NULL;
4246}
4247
4248
4249// Pattern ::
4250// Disjunction
4251RegExpTree* RegExpParser::ParsePattern() {
4252 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4253 ASSERT(!has_more());
4254 // If the result of parsing is a literal string atom, and it has the
4255 // same length as the input, then the atom is identical to the input.
4256 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4257 simple_ = true;
4258 }
4259 return result;
4260}
4261
4262
4263// Disjunction ::
4264// Alternative
4265// Alternative | Disjunction
4266// Alternative ::
4267// [empty]
4268// Term Alternative
4269// Term ::
4270// Assertion
4271// Atom
4272// Atom Quantifier
4273RegExpTree* RegExpParser::ParseDisjunction() {
4274 // Used to store current state while parsing subexpressions.
4275 RegExpParserState initial_state(NULL, INITIAL, 0);
4276 RegExpParserState* stored_state = &initial_state;
4277 // Cache the builder in a local variable for quick access.
4278 RegExpBuilder* builder = initial_state.builder();
4279 while (true) {
4280 switch (current()) {
4281 case kEndMarker:
4282 if (stored_state->IsSubexpression()) {
4283 // Inside a parenthesized group when hitting end of input.
4284 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4285 }
4286 ASSERT_EQ(INITIAL, stored_state->group_type());
4287 // Parsing completed successfully.
4288 return builder->ToRegExp();
4289 case ')': {
4290 if (!stored_state->IsSubexpression()) {
4291 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4292 }
4293 ASSERT_NE(INITIAL, stored_state->group_type());
4294
4295 Advance();
4296 // End disjunction parsing and convert builder content to new single
4297 // regexp atom.
4298 RegExpTree* body = builder->ToRegExp();
4299
4300 int end_capture_index = captures_started();
4301
4302 int capture_index = stored_state->capture_index();
4303 SubexpressionType type = stored_state->group_type();
4304
4305 // Restore previous state.
4306 stored_state = stored_state->previous_state();
4307 builder = stored_state->builder();
4308
4309 // Build result of subexpression.
4310 if (type == CAPTURE) {
4311 RegExpCapture* capture = new RegExpCapture(body, capture_index);
4312 captures_->at(capture_index - 1) = capture;
4313 body = capture;
4314 } else if (type != GROUPING) {
4315 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4316 bool is_positive = (type == POSITIVE_LOOKAHEAD);
4317 body = new RegExpLookahead(body,
4318 is_positive,
4319 end_capture_index - capture_index,
4320 capture_index);
4321 }
4322 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004323 // For compatability with JSC and ES3, we allow quantifiers after
4324 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004325 break;
4326 }
4327 case '|': {
4328 Advance();
4329 builder->NewAlternative();
4330 continue;
4331 }
4332 case '*':
4333 case '+':
4334 case '?':
4335 return ReportError(CStrVector("Nothing to repeat"));
4336 case '^': {
4337 Advance();
4338 if (multiline_) {
4339 builder->AddAssertion(
4340 new RegExpAssertion(RegExpAssertion::START_OF_LINE));
4341 } else {
4342 builder->AddAssertion(
4343 new RegExpAssertion(RegExpAssertion::START_OF_INPUT));
4344 set_contains_anchor();
4345 }
4346 continue;
4347 }
4348 case '$': {
4349 Advance();
4350 RegExpAssertion::Type type =
4351 multiline_ ? RegExpAssertion::END_OF_LINE :
4352 RegExpAssertion::END_OF_INPUT;
4353 builder->AddAssertion(new RegExpAssertion(type));
4354 continue;
4355 }
4356 case '.': {
4357 Advance();
4358 // everything except \x0a, \x0d, \u2028 and \u2029
4359 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4360 CharacterRange::AddClassEscape('.', ranges);
4361 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
4362 builder->AddAtom(atom);
4363 break;
4364 }
4365 case '(': {
4366 SubexpressionType type = CAPTURE;
4367 Advance();
4368 if (current() == '?') {
4369 switch (Next()) {
4370 case ':':
4371 type = GROUPING;
4372 break;
4373 case '=':
4374 type = POSITIVE_LOOKAHEAD;
4375 break;
4376 case '!':
4377 type = NEGATIVE_LOOKAHEAD;
4378 break;
4379 default:
4380 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4381 break;
4382 }
4383 Advance(2);
4384 } else {
4385 if (captures_ == NULL) {
4386 captures_ = new ZoneList<RegExpCapture*>(2);
4387 }
4388 if (captures_started() >= kMaxCaptures) {
4389 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4390 }
4391 captures_->Add(NULL);
4392 }
4393 // Store current state and begin new disjunction parsing.
4394 stored_state = new RegExpParserState(stored_state,
4395 type,
4396 captures_started());
4397 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004398 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004399 }
4400 case '[': {
4401 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4402 builder->AddAtom(atom);
4403 break;
4404 }
4405 // Atom ::
4406 // \ AtomEscape
4407 case '\\':
4408 switch (Next()) {
4409 case kEndMarker:
4410 return ReportError(CStrVector("\\ at end of pattern"));
4411 case 'b':
4412 Advance(2);
4413 builder->AddAssertion(
4414 new RegExpAssertion(RegExpAssertion::BOUNDARY));
4415 continue;
4416 case 'B':
4417 Advance(2);
4418 builder->AddAssertion(
4419 new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
4420 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004421 // AtomEscape ::
4422 // CharacterClassEscape
4423 //
4424 // CharacterClassEscape :: one of
4425 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004426 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4427 uc32 c = Next();
4428 Advance(2);
4429 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4430 CharacterRange::AddClassEscape(c, ranges);
4431 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
4432 builder->AddAtom(atom);
4433 break;
4434 }
4435 case '1': case '2': case '3': case '4': case '5': case '6':
4436 case '7': case '8': case '9': {
4437 int index = 0;
4438 if (ParseBackReferenceIndex(&index)) {
4439 RegExpCapture* capture = NULL;
4440 if (captures_ != NULL && index <= captures_->length()) {
4441 capture = captures_->at(index - 1);
4442 }
4443 if (capture == NULL) {
4444 builder->AddEmpty();
4445 break;
4446 }
4447 RegExpTree* atom = new RegExpBackReference(capture);
4448 builder->AddAtom(atom);
4449 break;
4450 }
4451 uc32 first_digit = Next();
4452 if (first_digit == '8' || first_digit == '9') {
4453 // Treat as identity escape
4454 builder->AddCharacter(first_digit);
4455 Advance(2);
4456 break;
4457 }
4458 }
4459 // FALLTHROUGH
4460 case '0': {
4461 Advance();
4462 uc32 octal = ParseOctalLiteral();
4463 builder->AddCharacter(octal);
4464 break;
4465 }
4466 // ControlEscape :: one of
4467 // f n r t v
4468 case 'f':
4469 Advance(2);
4470 builder->AddCharacter('\f');
4471 break;
4472 case 'n':
4473 Advance(2);
4474 builder->AddCharacter('\n');
4475 break;
4476 case 'r':
4477 Advance(2);
4478 builder->AddCharacter('\r');
4479 break;
4480 case 't':
4481 Advance(2);
4482 builder->AddCharacter('\t');
4483 break;
4484 case 'v':
4485 Advance(2);
4486 builder->AddCharacter('\v');
4487 break;
4488 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004489 Advance();
4490 uc32 controlLetter = Next();
4491 // Special case if it is an ASCII letter.
4492 // Convert lower case letters to uppercase.
4493 uc32 letter = controlLetter & ~('a' ^ 'A');
4494 if (letter < 'A' || 'Z' < letter) {
4495 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4496 // This is outside the specification. We match JSC in
4497 // reading the backslash as a literal character instead
4498 // of as starting an escape.
4499 builder->AddCharacter('\\');
4500 } else {
4501 Advance(2);
4502 builder->AddCharacter(controlLetter & 0x1f);
4503 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004504 break;
4505 }
4506 case 'x': {
4507 Advance(2);
4508 uc32 value;
4509 if (ParseHexEscape(2, &value)) {
4510 builder->AddCharacter(value);
4511 } else {
4512 builder->AddCharacter('x');
4513 }
4514 break;
4515 }
4516 case 'u': {
4517 Advance(2);
4518 uc32 value;
4519 if (ParseHexEscape(4, &value)) {
4520 builder->AddCharacter(value);
4521 } else {
4522 builder->AddCharacter('u');
4523 }
4524 break;
4525 }
4526 default:
4527 // Identity escape.
4528 builder->AddCharacter(Next());
4529 Advance(2);
4530 break;
4531 }
4532 break;
4533 case '{': {
4534 int dummy;
4535 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4536 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4537 }
4538 // fallthrough
4539 }
4540 default:
4541 builder->AddCharacter(current());
4542 Advance();
4543 break;
4544 } // end switch(current())
4545
4546 int min;
4547 int max;
4548 switch (current()) {
4549 // QuantifierPrefix ::
4550 // *
4551 // +
4552 // ?
4553 // {
4554 case '*':
4555 min = 0;
4556 max = RegExpTree::kInfinity;
4557 Advance();
4558 break;
4559 case '+':
4560 min = 1;
4561 max = RegExpTree::kInfinity;
4562 Advance();
4563 break;
4564 case '?':
4565 min = 0;
4566 max = 1;
4567 Advance();
4568 break;
4569 case '{':
4570 if (ParseIntervalQuantifier(&min, &max)) {
4571 if (max < min) {
4572 ReportError(CStrVector("numbers out of order in {} quantifier.")
4573 CHECK_FAILED);
4574 }
4575 break;
4576 } else {
4577 continue;
4578 }
4579 default:
4580 continue;
4581 }
Leon Clarkee46be812010-01-19 14:06:41 +00004582 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004583 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004584 type = RegExpQuantifier::NON_GREEDY;
4585 Advance();
4586 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4587 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4588 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004589 Advance();
4590 }
Leon Clarkee46be812010-01-19 14:06:41 +00004591 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004592 }
4593}
4594
4595class SourceCharacter {
4596 public:
4597 static bool Is(uc32 c) {
4598 switch (c) {
4599 // case ']': case '}':
4600 // In spidermonkey and jsc these are treated as source characters
4601 // so we do too.
4602 case '^': case '$': case '\\': case '.': case '*': case '+':
4603 case '?': case '(': case ')': case '[': case '{': case '|':
4604 case RegExpParser::kEndMarker:
4605 return false;
4606 default:
4607 return true;
4608 }
4609 }
4610};
4611
4612
4613static unibrow::Predicate<SourceCharacter> source_character;
4614
4615
4616static inline bool IsSourceCharacter(uc32 c) {
4617 return source_character.get(c);
4618}
4619
4620#ifdef DEBUG
4621// Currently only used in an ASSERT.
4622static bool IsSpecialClassEscape(uc32 c) {
4623 switch (c) {
4624 case 'd': case 'D':
4625 case 's': case 'S':
4626 case 'w': case 'W':
4627 return true;
4628 default:
4629 return false;
4630 }
4631}
4632#endif
4633
4634
4635// In order to know whether an escape is a backreference or not we have to scan
4636// the entire regexp and find the number of capturing parentheses. However we
4637// don't want to scan the regexp twice unless it is necessary. This mini-parser
4638// is called when needed. It can see the difference between capturing and
4639// noncapturing parentheses and can skip character classes and backslash-escaped
4640// characters.
4641void RegExpParser::ScanForCaptures() {
4642 // Start with captures started previous to current position
4643 int capture_count = captures_started();
4644 // Add count of captures after this position.
4645 int n;
4646 while ((n = current()) != kEndMarker) {
4647 Advance();
4648 switch (n) {
4649 case '\\':
4650 Advance();
4651 break;
4652 case '[': {
4653 int c;
4654 while ((c = current()) != kEndMarker) {
4655 Advance();
4656 if (c == '\\') {
4657 Advance();
4658 } else {
4659 if (c == ']') break;
4660 }
4661 }
4662 break;
4663 }
4664 case '(':
4665 if (current() != '?') capture_count++;
4666 break;
4667 }
4668 }
4669 capture_count_ = capture_count;
4670 is_scanned_for_captures_ = true;
4671}
4672
4673
4674bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4675 ASSERT_EQ('\\', current());
4676 ASSERT('1' <= Next() && Next() <= '9');
4677 // Try to parse a decimal literal that is no greater than the total number
4678 // of left capturing parentheses in the input.
4679 int start = position();
4680 int value = Next() - '0';
4681 Advance(2);
4682 while (true) {
4683 uc32 c = current();
4684 if (IsDecimalDigit(c)) {
4685 value = 10 * value + (c - '0');
4686 if (value > kMaxCaptures) {
4687 Reset(start);
4688 return false;
4689 }
4690 Advance();
4691 } else {
4692 break;
4693 }
4694 }
4695 if (value > captures_started()) {
4696 if (!is_scanned_for_captures_) {
4697 int saved_position = position();
4698 ScanForCaptures();
4699 Reset(saved_position);
4700 }
4701 if (value > capture_count_) {
4702 Reset(start);
4703 return false;
4704 }
4705 }
4706 *index_out = value;
4707 return true;
4708}
4709
4710
4711// QuantifierPrefix ::
4712// { DecimalDigits }
4713// { DecimalDigits , }
4714// { DecimalDigits , DecimalDigits }
4715//
4716// Returns true if parsing succeeds, and set the min_out and max_out
4717// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4718bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4719 ASSERT_EQ(current(), '{');
4720 int start = position();
4721 Advance();
4722 int min = 0;
4723 if (!IsDecimalDigit(current())) {
4724 Reset(start);
4725 return false;
4726 }
4727 while (IsDecimalDigit(current())) {
4728 int next = current() - '0';
4729 if (min > (RegExpTree::kInfinity - next) / 10) {
4730 // Overflow. Skip past remaining decimal digits and return -1.
4731 do {
4732 Advance();
4733 } while (IsDecimalDigit(current()));
4734 min = RegExpTree::kInfinity;
4735 break;
4736 }
4737 min = 10 * min + next;
4738 Advance();
4739 }
4740 int max = 0;
4741 if (current() == '}') {
4742 max = min;
4743 Advance();
4744 } else if (current() == ',') {
4745 Advance();
4746 if (current() == '}') {
4747 max = RegExpTree::kInfinity;
4748 Advance();
4749 } else {
4750 while (IsDecimalDigit(current())) {
4751 int next = current() - '0';
4752 if (max > (RegExpTree::kInfinity - next) / 10) {
4753 do {
4754 Advance();
4755 } while (IsDecimalDigit(current()));
4756 max = RegExpTree::kInfinity;
4757 break;
4758 }
4759 max = 10 * max + next;
4760 Advance();
4761 }
4762 if (current() != '}') {
4763 Reset(start);
4764 return false;
4765 }
4766 Advance();
4767 }
4768 } else {
4769 Reset(start);
4770 return false;
4771 }
4772 *min_out = min;
4773 *max_out = max;
4774 return true;
4775}
4776
4777
Steve Blocka7e24c12009-10-30 11:49:00 +00004778uc32 RegExpParser::ParseOctalLiteral() {
4779 ASSERT('0' <= current() && current() <= '7');
4780 // For compatibility with some other browsers (not all), we parse
4781 // up to three octal digits with a value below 256.
4782 uc32 value = current() - '0';
4783 Advance();
4784 if ('0' <= current() && current() <= '7') {
4785 value = value * 8 + current() - '0';
4786 Advance();
4787 if (value < 32 && '0' <= current() && current() <= '7') {
4788 value = value * 8 + current() - '0';
4789 Advance();
4790 }
4791 }
4792 return value;
4793}
4794
4795
4796bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4797 int start = position();
4798 uc32 val = 0;
4799 bool done = false;
4800 for (int i = 0; !done; i++) {
4801 uc32 c = current();
4802 int d = HexValue(c);
4803 if (d < 0) {
4804 Reset(start);
4805 return false;
4806 }
4807 val = val * 16 + d;
4808 Advance();
4809 if (i == length - 1) {
4810 done = true;
4811 }
4812 }
4813 *value = val;
4814 return true;
4815}
4816
4817
4818uc32 RegExpParser::ParseClassCharacterEscape() {
4819 ASSERT(current() == '\\');
4820 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4821 Advance();
4822 switch (current()) {
4823 case 'b':
4824 Advance();
4825 return '\b';
4826 // ControlEscape :: one of
4827 // f n r t v
4828 case 'f':
4829 Advance();
4830 return '\f';
4831 case 'n':
4832 Advance();
4833 return '\n';
4834 case 'r':
4835 Advance();
4836 return '\r';
4837 case 't':
4838 Advance();
4839 return '\t';
4840 case 'v':
4841 Advance();
4842 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004843 case 'c': {
4844 uc32 controlLetter = Next();
4845 uc32 letter = controlLetter & ~('A' ^ 'a');
4846 // For compatibility with JSC, inside a character class
4847 // we also accept digits and underscore as control characters.
4848 if ((controlLetter >= '0' && controlLetter <= '9') ||
4849 controlLetter == '_' ||
4850 (letter >= 'A' && letter <= 'Z')) {
4851 Advance(2);
4852 // Control letters mapped to ASCII control characters in the range
4853 // 0x00-0x1f.
4854 return controlLetter & 0x1f;
4855 }
4856 // We match JSC in reading the backslash as a literal
4857 // character instead of as starting an escape.
4858 return '\\';
4859 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004860 case '0': case '1': case '2': case '3': case '4': case '5':
4861 case '6': case '7':
4862 // For compatibility, we interpret a decimal escape that isn't
4863 // a back reference (and therefore either \0 or not valid according
4864 // to the specification) as a 1..3 digit octal character code.
4865 return ParseOctalLiteral();
4866 case 'x': {
4867 Advance();
4868 uc32 value;
4869 if (ParseHexEscape(2, &value)) {
4870 return value;
4871 }
4872 // If \x is not followed by a two-digit hexadecimal, treat it
4873 // as an identity escape.
4874 return 'x';
4875 }
4876 case 'u': {
4877 Advance();
4878 uc32 value;
4879 if (ParseHexEscape(4, &value)) {
4880 return value;
4881 }
4882 // If \u is not followed by a four-digit hexadecimal, treat it
4883 // as an identity escape.
4884 return 'u';
4885 }
4886 default: {
4887 // Extended identity escape. We accept any character that hasn't
4888 // been matched by a more specific case, not just the subset required
4889 // by the ECMAScript specification.
4890 uc32 result = current();
4891 Advance();
4892 return result;
4893 }
4894 }
4895 return 0;
4896}
4897
4898
4899CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4900 ASSERT_EQ(0, *char_class);
4901 uc32 first = current();
4902 if (first == '\\') {
4903 switch (Next()) {
4904 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4905 *char_class = Next();
4906 Advance(2);
4907 return CharacterRange::Singleton(0); // Return dummy value.
4908 }
4909 case kEndMarker:
4910 return ReportError(CStrVector("\\ at end of pattern"));
4911 default:
4912 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4913 return CharacterRange::Singleton(c);
4914 }
4915 } else {
4916 Advance();
4917 return CharacterRange::Singleton(first);
4918 }
4919}
4920
4921
Ben Murdochb0fe1622011-05-05 13:52:32 +01004922static const uc16 kNoCharClass = 0;
4923
4924// Adds range or pre-defined character class to character ranges.
4925// If char_class is not kInvalidClass, it's interpreted as a class
4926// escape (i.e., 's' means whitespace, from '\s').
4927static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4928 uc16 char_class,
4929 CharacterRange range) {
4930 if (char_class != kNoCharClass) {
4931 CharacterRange::AddClassEscape(char_class, ranges);
4932 } else {
4933 ranges->Add(range);
4934 }
4935}
4936
4937
Steve Blocka7e24c12009-10-30 11:49:00 +00004938RegExpTree* RegExpParser::ParseCharacterClass() {
4939 static const char* kUnterminated = "Unterminated character class";
4940 static const char* kRangeOutOfOrder = "Range out of order in character class";
4941
4942 ASSERT_EQ(current(), '[');
4943 Advance();
4944 bool is_negated = false;
4945 if (current() == '^') {
4946 is_negated = true;
4947 Advance();
4948 }
4949 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4950 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004951 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004952 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004953 if (current() == '-') {
4954 Advance();
4955 if (current() == kEndMarker) {
4956 // If we reach the end we break out of the loop and let the
4957 // following code report an error.
4958 break;
4959 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004960 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004961 ranges->Add(CharacterRange::Singleton('-'));
4962 break;
4963 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004964 uc16 char_class_2 = kNoCharClass;
4965 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4966 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4967 // Either end is an escaped character class. Treat the '-' verbatim.
4968 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004969 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004970 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004971 continue;
4972 }
4973 if (first.from() > next.to()) {
4974 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4975 }
4976 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4977 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004978 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004979 }
4980 }
4981 if (!has_more()) {
4982 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4983 }
4984 Advance();
4985 if (ranges->length() == 0) {
4986 ranges->Add(CharacterRange::Everything());
4987 is_negated = !is_negated;
4988 }
4989 return new RegExpCharacterClass(ranges, is_negated);
4990}
4991
4992
4993// ----------------------------------------------------------------------------
4994// The Parser interface.
4995
Steve Blocka7e24c12009-10-30 11:49:00 +00004996ParserMessage::~ParserMessage() {
4997 for (int i = 0; i < args().length(); i++)
4998 DeleteArray(args()[i]);
4999 DeleteArray(args().start());
5000}
5001
5002
5003ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01005004 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00005005}
5006
5007
5008int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01005009 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00005010}
5011
5012
Leon Clarkef7060e22010-06-03 12:02:55 +01005013const char* ScriptDataImpl::Data() {
5014 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00005015}
5016
5017
Leon Clarkee46be812010-01-19 14:06:41 +00005018bool ScriptDataImpl::HasError() {
5019 return has_error();
5020}
5021
5022
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005023void ScriptDataImpl::Initialize() {
5024 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005025 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5026 function_index_ = PreparseDataConstants::kHeaderSize;
5027 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5028 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005029 if (store_.length() > symbol_data_offset) {
5030 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5031 } else {
5032 // Partial preparse causes no symbol information.
5033 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5034 }
5035 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5036 }
5037}
5038
5039
5040int ScriptDataImpl::ReadNumber(byte** source) {
5041 // Reads a number from symbol_data_ in base 128. The most significant
5042 // bit marks that there are more digits.
5043 // If the first byte is 0x80 (kNumberTerminator), it would normally
5044 // represent a leading zero. Since that is useless, and therefore won't
5045 // appear as the first digit of any actual value, it is used to
5046 // mark the end of the input stream.
5047 byte* data = *source;
5048 if (data >= symbol_data_end_) return -1;
5049 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005050 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005051 // End of stream marker.
5052 return -1;
5053 }
5054 int result = input & 0x7f;
5055 data++;
5056 while ((input & 0x80u) != 0) {
5057 if (data >= symbol_data_end_) return -1;
5058 input = *data;
5059 result = (result << 7) | (input & 0x7f);
5060 data++;
5061 }
5062 *source = data;
5063 return result;
5064}
5065
5066
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005067// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005068static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005069 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01005070 ParserRecorder* recorder) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005071 V8JavaScriptScanner scanner;
Steve Block9fac8402011-05-12 15:51:54 +01005072 scanner.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005073 intptr_t stack_limit = StackGuard::real_climit();
5074 if (!preparser::PreParser::PreParseProgram(&scanner,
5075 recorder,
5076 allow_lazy,
5077 stack_limit)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005078 Top::StackOverflow();
5079 return NULL;
5080 }
5081
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005082 // Extract the accumulated data from the recorder as a single
5083 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005084 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005085 return new ScriptDataImpl(store);
5086}
5087
5088
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005089// Preparse, but only collect data that is immediately useful,
5090// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005091ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005092 v8::Extension* extension) {
5093 bool allow_lazy = FLAG_lazy && (extension == NULL);
5094 if (!allow_lazy) {
5095 // Partial preparsing is only about lazily compiled functions.
5096 // If we don't allow lazy compilation, the log data will be empty.
5097 return NULL;
5098 }
5099 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005100 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005101}
5102
5103
Ben Murdochb0fe1622011-05-05 13:52:32 +01005104ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005105 v8::Extension* extension) {
5106 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005107 bool allow_lazy = FLAG_lazy && (extension == NULL);
5108 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01005109 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005110}
5111
5112
5113bool RegExpParser::ParseRegExp(FlatStringReader* input,
5114 bool multiline,
5115 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005116 ASSERT(result != NULL);
5117 RegExpParser parser(input, &result->error, multiline);
5118 RegExpTree* tree = parser.ParsePattern();
5119 if (parser.failed()) {
5120 ASSERT(tree == NULL);
5121 ASSERT(!result->error.is_null());
5122 } else {
5123 ASSERT(tree != NULL);
5124 ASSERT(result->error.is_null());
5125 result->tree = tree;
5126 int capture_count = parser.captures_started();
5127 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5128 result->contains_anchor = parser.contains_anchor();
5129 result->capture_count = capture_count;
5130 }
5131 return !parser.failed();
5132}
5133
5134
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005135bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005136 ASSERT(info->function() == NULL);
5137 FunctionLiteral* result = NULL;
5138 Handle<Script> script = info->script();
5139 if (info->is_lazy()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005140 Parser parser(script, true, NULL, NULL);
Ben Murdochf87a2032010-10-22 12:50:53 +01005141 result = parser.ParseLazy(info->shared_info());
Leon Clarke4515c472010-02-03 11:58:03 +00005142 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01005143 bool allow_natives_syntax =
5144 FLAG_allow_natives_syntax || Bootstrapper::IsActive();
5145 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005146 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01005147 if (pre_data != NULL && pre_data->has_error()) {
5148 Scanner::Location loc = pre_data->MessageLocation();
5149 const char* message = pre_data->BuildMessage();
5150 Vector<const char*> args = pre_data->BuildArgs();
5151 parser.ReportMessageAt(loc, message, args);
5152 DeleteArray(message);
5153 for (int i = 0; i < args.length(); i++) {
5154 DeleteArray(args[i]);
5155 }
5156 DeleteArray(args.start());
5157 ASSERT(Top::has_pending_exception());
5158 } else {
5159 Handle<String> source = Handle<String>(String::cast(script->source()));
Steve Block1e0659c2011-05-24 12:43:12 +01005160 result = parser.ParseProgram(source,
5161 info->is_global(),
5162 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01005163 }
Leon Clarke4515c472010-02-03 11:58:03 +00005164 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005165
5166 info->SetFunction(result);
5167 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005168}
5169
Steve Blocka7e24c12009-10-30 11:49:00 +00005170} } // namespace v8::internal