blob: 381ff27143b4faf7cc028d7952e5471e0fa85e8e [file] [log] [blame]
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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#ifndef V8_PARSER_H_
29#define V8_PARSER_H_
30
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000031#include "allocation.h"
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000032#include "ast.h"
33#include "scanner.h"
lrn@chromium.orgfa943b72010-11-03 08:14:36 +000034#include "scopes.h"
lrn@chromium.org1c092762011-05-09 09:42:16 +000035#include "preparse-data-format.h"
ager@chromium.orgbeb25712010-11-29 08:02:25 +000036#include "preparse-data.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
kasperl@chromium.org71affb52009-05-26 05:44:31 +000038namespace v8 {
39namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000040
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000041class CompilationInfo;
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000042class FuncNameInferrer;
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000043class ParserLog;
44class PositionStack;
45class Target;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000046class LexicalScope;
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000047
48template <typename T> class ZoneListWrapper;
49
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050
51class ParserMessage : public Malloced {
52 public:
53 ParserMessage(Scanner::Location loc, const char* message,
54 Vector<const char*> args)
55 : loc_(loc),
56 message_(message),
57 args_(args) { }
58 ~ParserMessage();
59 Scanner::Location location() { return loc_; }
60 const char* message() { return message_; }
61 Vector<const char*> args() { return args_; }
62 private:
63 Scanner::Location loc_;
64 const char* message_;
65 Vector<const char*> args_;
66};
67
68
69class FunctionEntry BASE_EMBEDDED {
70 public:
71 explicit FunctionEntry(Vector<unsigned> backing) : backing_(backing) { }
72 FunctionEntry() : backing_(Vector<unsigned>::empty()) { }
73
74 int start_pos() { return backing_[kStartPosOffset]; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000075 int end_pos() { return backing_[kEndPosOffset]; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076 int literal_count() { return backing_[kLiteralCountOffset]; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077 int property_count() { return backing_[kPropertyCountOffset]; }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000078 bool strict_mode() { return backing_[kStrictModeOffset] != 0; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000079
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 bool is_valid() { return backing_.length() > 0; }
81
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000082 static const int kSize = 5;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000083
84 private:
85 Vector<unsigned> backing_;
86 static const int kStartPosOffset = 0;
87 static const int kEndPosOffset = 1;
88 static const int kLiteralCountOffset = 2;
89 static const int kPropertyCountOffset = 3;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000090 static const int kStrictModeOffset = 4;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091};
92
93
94class ScriptDataImpl : public ScriptData {
95 public:
96 explicit ScriptDataImpl(Vector<unsigned> store)
97 : store_(store),
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000098 owns_store_(true) { }
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000099
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000100 // Create an empty ScriptDataImpl that is guaranteed to not satisfy
101 // a SanityCheck.
102 ScriptDataImpl() : store_(Vector<unsigned>()), owns_store_(false) { }
103
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104 virtual ~ScriptDataImpl();
105 virtual int Length();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000106 virtual const char* Data();
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000107 virtual bool HasError();
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000108
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000109 void Initialize();
110 void ReadNextSymbolPosition();
111
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000112 FunctionEntry GetFunctionEntry(int start);
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000113 int GetSymbolIdentifier();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114 bool SanityCheck();
115
116 Scanner::Location MessageLocation();
117 const char* BuildMessage();
118 Vector<const char*> BuildArgs();
119
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000120 int symbol_count() {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000121 return (store_.length() > PreparseDataConstants::kHeaderSize)
122 ? store_[PreparseDataConstants::kSymbolCountOffset]
123 : 0;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000124 }
125 // The following functions should only be called if SanityCheck has
126 // returned true.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000127 bool has_error() { return store_[PreparseDataConstants::kHasErrorOffset]; }
128 unsigned magic() { return store_[PreparseDataConstants::kMagicOffset]; }
129 unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000130
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131 private:
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000132 Vector<unsigned> store_;
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000133 unsigned char* symbol_data_;
134 unsigned char* symbol_data_end_;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000135 int function_index_;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000136 bool owns_store_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000137
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138 unsigned Read(int position);
139 unsigned* ReadAddress(int position);
erik.corry@gmail.comd88afa22010-09-15 12:33:05 +0000140 // Reads a number from the current symbols
141 int ReadNumber(byte** source);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000143 ScriptDataImpl(const char* backing_store, int length)
144 : store_(reinterpret_cast<unsigned*>(const_cast<char*>(backing_store)),
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000145 length / static_cast<int>(sizeof(unsigned))),
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000146 owns_store_(false) {
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000147 ASSERT_EQ(0, static_cast<int>(
148 reinterpret_cast<intptr_t>(backing_store) % sizeof(unsigned)));
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000149 }
150
ricow@chromium.org65fae842010-08-25 15:26:24 +0000151 // Read strings written by ParserRecorder::WriteString.
152 static const char* ReadString(unsigned* start, int* chars);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000153
154 friend class ScriptData;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155};
156
157
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000158class ParserApi {
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000159 public:
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000160 // Parses the source code represented by the compilation info and sets its
161 // function literal. Returns false (and deallocates any allocated AST
162 // nodes) if parsing failed.
163 static bool Parse(CompilationInfo* info);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000164
165 // Generic preparser generating full preparse data.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000166 static ScriptDataImpl* PreParse(UC16CharacterStream* source,
danno@chromium.orgb6451162011-08-17 14:33:23 +0000167 v8::Extension* extension,
168 bool harmony_block_scoping);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000169
170 // Preparser that only does preprocessing that makes sense if only used
171 // immediately after.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000172 static ScriptDataImpl* PartialPreParse(UC16CharacterStream* source,
danno@chromium.orgb6451162011-08-17 14:33:23 +0000173 v8::Extension* extension,
174 bool harmony_block_scoping);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000175};
176
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000177// ----------------------------------------------------------------------------
178// REGEXP PARSING
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000179
180// A BuffferedZoneList is an automatically growing list, just like (and backed
181// by) a ZoneList, that is optimized for the case of adding and removing
182// a single element. The last element added is stored outside the backing list,
183// and if no more than one element is ever added, the ZoneList isn't even
184// allocated.
185// Elements must not be NULL pointers.
186template <typename T, int initial_size>
187class BufferedZoneList {
188 public:
189 BufferedZoneList() : list_(NULL), last_(NULL) {}
190
191 // Adds element at end of list. This element is buffered and can
192 // be read using last() or removed using RemoveLast until a new Add or until
193 // RemoveLast or GetList has been called.
194 void Add(T* value) {
195 if (last_ != NULL) {
196 if (list_ == NULL) {
197 list_ = new ZoneList<T*>(initial_size);
198 }
199 list_->Add(last_);
200 }
201 last_ = value;
202 }
203
204 T* last() {
205 ASSERT(last_ != NULL);
206 return last_;
207 }
208
209 T* RemoveLast() {
210 ASSERT(last_ != NULL);
211 T* result = last_;
212 if ((list_ != NULL) && (list_->length() > 0))
213 last_ = list_->RemoveLast();
214 else
215 last_ = NULL;
216 return result;
217 }
218
219 T* Get(int i) {
220 ASSERT((0 <= i) && (i < length()));
221 if (list_ == NULL) {
222 ASSERT_EQ(0, i);
223 return last_;
224 } else {
225 if (i == list_->length()) {
226 ASSERT(last_ != NULL);
227 return last_;
228 } else {
229 return list_->at(i);
230 }
231 }
232 }
233
234 void Clear() {
235 list_ = NULL;
236 last_ = NULL;
237 }
238
239 int length() {
240 int length = (list_ == NULL) ? 0 : list_->length();
241 return length + ((last_ == NULL) ? 0 : 1);
242 }
243
244 ZoneList<T*>* GetList() {
245 if (list_ == NULL) {
246 list_ = new ZoneList<T*>(initial_size);
247 }
248 if (last_ != NULL) {
249 list_->Add(last_);
250 last_ = NULL;
251 }
252 return list_;
253 }
254
255 private:
256 ZoneList<T*>* list_;
257 T* last_;
258};
259
260
261// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
262class RegExpBuilder: public ZoneObject {
263 public:
264 RegExpBuilder();
265 void AddCharacter(uc16 character);
266 // "Adds" an empty expression. Does nothing except consume a
267 // following quantifier
268 void AddEmpty();
269 void AddAtom(RegExpTree* tree);
270 void AddAssertion(RegExpTree* tree);
271 void NewAlternative(); // '|'
272 void AddQuantifierToAtom(int min, int max, RegExpQuantifier::Type type);
273 RegExpTree* ToRegExp();
274
275 private:
276 void FlushCharacters();
277 void FlushText();
278 void FlushTerms();
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000279 Zone* zone() { return zone_; }
280
281 Zone* zone_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000282 bool pending_empty_;
283 ZoneList<uc16>* characters_;
284 BufferedZoneList<RegExpTree, 2> terms_;
285 BufferedZoneList<RegExpTree, 2> text_;
286 BufferedZoneList<RegExpTree, 2> alternatives_;
287#ifdef DEBUG
288 enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_;
289#define LAST(x) last_added_ = x;
290#else
291#define LAST(x)
292#endif
293};
294
295
296class RegExpParser {
297 public:
298 RegExpParser(FlatStringReader* in,
299 Handle<String>* error,
300 bool multiline_mode);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000301
302 static bool ParseRegExp(FlatStringReader* input,
303 bool multiline,
304 RegExpCompileData* result);
305
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000306 RegExpTree* ParsePattern();
307 RegExpTree* ParseDisjunction();
308 RegExpTree* ParseGroup();
309 RegExpTree* ParseCharacterClass();
310
311 // Parses a {...,...} quantifier and stores the range in the given
312 // out parameters.
313 bool ParseIntervalQuantifier(int* min_out, int* max_out);
314
315 // Parses and returns a single escaped character. The character
316 // must not be 'b' or 'B' since they are usually handle specially.
317 uc32 ParseClassCharacterEscape();
318
319 // Checks whether the following is a length-digit hexadecimal number,
320 // and sets the value if it is.
321 bool ParseHexEscape(int length, uc32* value);
322
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000323 uc32 ParseOctalLiteral();
324
325 // Tries to parse the input as a back reference. If successful it
326 // stores the result in the output parameter and returns true. If
327 // it fails it will push back the characters read so the same characters
328 // can be reparsed.
329 bool ParseBackReferenceIndex(int* index_out);
330
331 CharacterRange ParseClassAtom(uc16* char_class);
332 RegExpTree* ReportError(Vector<const char> message);
333 void Advance();
334 void Advance(int dist);
335 void Reset(int pos);
336
337 // Reports whether the pattern might be used as a literal search string.
338 // Only use if the result of the parse is a single atom node.
339 bool simple();
340 bool contains_anchor() { return contains_anchor_; }
341 void set_contains_anchor() { contains_anchor_ = true; }
342 int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
343 int position() { return next_pos_ - 1; }
344 bool failed() { return failed_; }
345
346 static const int kMaxCaptures = 1 << 16;
347 static const uc32 kEndMarker = (1 << 21);
348
349 private:
350 enum SubexpressionType {
351 INITIAL,
352 CAPTURE, // All positive values represent captures.
353 POSITIVE_LOOKAHEAD,
354 NEGATIVE_LOOKAHEAD,
355 GROUPING
356 };
357
358 class RegExpParserState : public ZoneObject {
359 public:
360 RegExpParserState(RegExpParserState* previous_state,
361 SubexpressionType group_type,
362 int disjunction_capture_index)
363 : previous_state_(previous_state),
364 builder_(new RegExpBuilder()),
365 group_type_(group_type),
366 disjunction_capture_index_(disjunction_capture_index) {}
367 // Parser state of containing expression, if any.
368 RegExpParserState* previous_state() { return previous_state_; }
369 bool IsSubexpression() { return previous_state_ != NULL; }
370 // RegExpBuilder building this regexp's AST.
371 RegExpBuilder* builder() { return builder_; }
372 // Type of regexp being parsed (parenthesized group or entire regexp).
373 SubexpressionType group_type() { return group_type_; }
374 // Index in captures array of first capture in this sub-expression, if any.
375 // Also the capture index of this sub-expression itself, if group_type
376 // is CAPTURE.
377 int capture_index() { return disjunction_capture_index_; }
378
379 private:
380 // Linked list implementation of stack of states.
381 RegExpParserState* previous_state_;
382 // Builder for the stored disjunction.
383 RegExpBuilder* builder_;
384 // Stored disjunction type (capture, look-ahead or grouping), if any.
385 SubexpressionType group_type_;
386 // Stored disjunction's capture index (if any).
387 int disjunction_capture_index_;
388 };
389
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000390 Isolate* isolate() { return isolate_; }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000391 Zone* zone() { return isolate_->zone(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000392
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000393 uc32 current() { return current_; }
394 bool has_more() { return has_more_; }
395 bool has_next() { return next_pos_ < in()->length(); }
396 uc32 Next();
397 FlatStringReader* in() { return in_; }
398 void ScanForCaptures();
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000399
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000400 Isolate* isolate_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000401 Handle<String>* error_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000402 ZoneList<RegExpCapture*>* captures_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000403 FlatStringReader* in_;
404 uc32 current_;
405 int next_pos_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000406 // The capture count is only valid after we have scanned for captures.
407 int capture_count_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000408 bool has_more_;
409 bool multiline_;
410 bool simple_;
411 bool contains_anchor_;
412 bool is_scanned_for_captures_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000413 bool failed_;
414};
415
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000416// ----------------------------------------------------------------------------
417// JAVASCRIPT PARSING
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000418
419class Parser {
420 public:
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000421 Parser(Handle<Script> script,
422 bool allow_natives_syntax,
423 v8::Extension* extension,
424 ScriptDataImpl* pre_data);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000425 virtual ~Parser() { }
426
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000427 // Returns NULL if parsing failed.
428 FunctionLiteral* ParseProgram(Handle<String> source,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000429 bool in_global_context,
430 StrictModeFlag strict_mode);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000431
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000432 FunctionLiteral* ParseLazy(CompilationInfo* info);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000433
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000434 void ReportMessageAt(Scanner::Location loc,
435 const char* message,
436 Vector<const char*> args);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000437 void ReportMessageAt(Scanner::Location loc,
438 const char* message,
439 Vector<Handle<String> > args);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000440 void SetHarmonyBlockScoping(bool block_scoping);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000441
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000442 private:
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000443 // Limit on number of function parameters is chosen arbitrarily.
444 // Code::Flags uses only the low 17 bits of num-parameters to
445 // construct a hashable id, so if more than 2^17 are allowed, this
446 // should be checked.
447 static const int kMaxNumFunctionParameters = 32766;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000448 static const int kMaxNumFunctionLocals = 32767;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000449 FunctionLiteral* ParseLazy(CompilationInfo* info,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000450 UC16CharacterStream* source,
451 ZoneScope* zone_scope);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000452 enum Mode {
453 PARSE_LAZILY,
454 PARSE_EAGERLY
455 };
456
danno@chromium.orgb6451162011-08-17 14:33:23 +0000457 enum VariableDeclarationContext {
458 kSourceElement,
459 kStatement,
460 kForStatement
461 };
462
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000463 Isolate* isolate() { return isolate_; }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000464 Zone* zone() { return isolate_->zone(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000465
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000466 // Called by ParseProgram after setting up the scanner.
467 FunctionLiteral* DoParseProgram(Handle<String> source,
468 bool in_global_context,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000469 StrictModeFlag strict_mode,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000470 ZoneScope* zone_scope);
471
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000472 // Report syntax error
473 void ReportUnexpectedToken(Token::Value token);
474 void ReportInvalidPreparseData(Handle<String> name, bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000475 void ReportMessage(const char* message, Vector<const char*> args);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000476
477 bool inside_with() const { return with_nesting_level_ > 0; }
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000478 JavaScriptScanner& scanner() { return scanner_; }
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000479 Mode mode() const { return mode_; }
480 ScriptDataImpl* pre_data() const { return pre_data_; }
481
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000482 // Check if the given string is 'eval' or 'arguments'.
483 bool IsEvalOrArguments(Handle<String> string);
484
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000485 // All ParseXXX functions take as the last argument an *ok parameter
486 // which is set to false if parsing failed; it is unchanged otherwise.
487 // By making the 'exception handling' explicit, we are forced to check
488 // for failure at the call sites.
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000489 void* ParseSourceElements(ZoneList<Statement*>* processor,
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000490 int end_token, bool* ok);
danno@chromium.orgb6451162011-08-17 14:33:23 +0000491 Statement* ParseSourceElement(ZoneStringList* labels, bool* ok);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000492 Statement* ParseStatement(ZoneStringList* labels, bool* ok);
493 Statement* ParseFunctionDeclaration(bool* ok);
494 Statement* ParseNativeDeclaration(bool* ok);
495 Block* ParseBlock(ZoneStringList* labels, bool* ok);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000496 Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
danno@chromium.orgb6451162011-08-17 14:33:23 +0000497 Block* ParseVariableStatement(VariableDeclarationContext var_context,
498 bool* ok);
499 Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000500 Handle<String>* out,
501 bool* ok);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000502 Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
503 bool* ok);
504 IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
505 Statement* ParseContinueStatement(bool* ok);
506 Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
507 Statement* ParseReturnStatement(bool* ok);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000508 Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
509 CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
510 SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
511 DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
512 WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
513 Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
514 Statement* ParseThrowStatement(bool* ok);
515 Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
516 TryStatement* ParseTryStatement(bool* ok);
517 DebuggerStatement* ParseDebuggerStatement(bool* ok);
518
519 Expression* ParseExpression(bool accept_IN, bool* ok);
520 Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
521 Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
522 Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
523 Expression* ParseUnaryExpression(bool* ok);
524 Expression* ParsePostfixExpression(bool* ok);
525 Expression* ParseLeftHandSideExpression(bool* ok);
526 Expression* ParseNewExpression(bool* ok);
527 Expression* ParseMemberExpression(bool* ok);
528 Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
529 Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
530 bool* ok);
531 Expression* ParsePrimaryExpression(bool* ok);
532 Expression* ParseArrayLiteral(bool* ok);
533 Expression* ParseObjectLiteral(bool* ok);
534 ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok);
535 Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
536
537 Expression* NewCompareNode(Token::Value op,
538 Expression* x,
539 Expression* y,
540 int position);
541
542 // Populate the constant properties fixed array for a materialized object
543 // literal.
544 void BuildObjectLiteralConstantProperties(
545 ZoneList<ObjectLiteral::Property*>* properties,
546 Handle<FixedArray> constants,
547 bool* is_simple,
548 bool* fast_elements,
549 int* depth);
550
551 // Populate the literals fixed array for a materialized array literal.
552 void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties,
553 Handle<FixedArray> constants,
554 bool* is_simple,
555 int* depth);
556
557 // Decide if a property should be in the object boilerplate.
558 bool IsBoilerplateProperty(ObjectLiteral::Property* property);
559 // If the expression is a literal, return the literal value;
560 // if the expression is a materialized literal and is simple return a
561 // compile time value as encoded by CompileTimeValue::GetValue().
562 // Otherwise, return undefined literal as the placeholder
563 // in the object literal boilerplate.
564 Handle<Object> GetBoilerplateValue(Expression* expression);
565
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000566 ZoneList<Expression*>* ParseArguments(bool* ok);
567 FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000568 bool name_is_reserved,
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000569 int function_token_position,
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000570 FunctionLiteral::Type type,
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000571 bool* ok);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000572
573
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000574 // Magical syntax support.
575 Expression* ParseV8Intrinsic(bool* ok);
576
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000577 INLINE(Token::Value peek()) {
578 if (stack_overflow_) return Token::ILLEGAL;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000579 return scanner().peek();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000580 }
581
582 INLINE(Token::Value Next()) {
583 // BUG 1215673: Find a thread safe way to set a stack limit in
584 // pre-parse mode. Otherwise, we cannot safely pre-parse from other
585 // threads.
586 if (stack_overflow_) {
587 return Token::ILLEGAL;
588 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000589 if (StackLimitCheck(isolate()).HasOverflowed()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000590 // Any further calls to Next or peek will return the illegal token.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000591 // The current call must return the next token, which might already
592 // have been peek'ed.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000593 stack_overflow_ = true;
594 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000595 return scanner().Next();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000596 }
597
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000598 bool peek_any_identifier();
599
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000600 INLINE(void Consume(Token::Value token));
601 void Expect(Token::Value token, bool* ok);
602 bool Check(Token::Value token);
603 void ExpectSemicolon(bool* ok);
604
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000605 Handle<String> LiteralString(PretenureFlag tenured) {
606 if (scanner().is_literal_ascii()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000607 return isolate_->factory()->NewStringFromAscii(
608 scanner().literal_ascii_string(), tenured);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000609 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000610 return isolate_->factory()->NewStringFromTwoByte(
611 scanner().literal_uc16_string(), tenured);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000612 }
613 }
614
615 Handle<String> NextLiteralString(PretenureFlag tenured) {
616 if (scanner().is_next_literal_ascii()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000617 return isolate_->factory()->NewStringFromAscii(
618 scanner().next_literal_ascii_string(), tenured);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000619 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000620 return isolate_->factory()->NewStringFromTwoByte(
621 scanner().next_literal_uc16_string(), tenured);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000622 }
623 }
624
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000625 Handle<String> GetSymbol(bool* ok);
626
627 // Get odd-ball literals.
628 Literal* GetLiteralUndefined();
629 Literal* GetLiteralTheHole();
630 Literal* GetLiteralNumber(double value);
631
632 Handle<String> ParseIdentifier(bool* ok);
ager@chromium.org04921a82011-06-27 13:21:41 +0000633 Handle<String> ParseIdentifierOrStrictReservedWord(
634 bool* is_strict_reserved, bool* ok);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000635 Handle<String> ParseIdentifierName(bool* ok);
ager@chromium.org04921a82011-06-27 13:21:41 +0000636 Handle<String> ParseIdentifierNameOrGetOrSet(bool* is_get,
637 bool* is_set,
638 bool* ok);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000639
ager@chromium.org378b34e2011-01-28 08:04:38 +0000640 // Strict mode validation of LValue expressions
641 void CheckStrictModeLValue(Expression* expression,
642 const char* error,
643 bool* ok);
644
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000645 // Strict mode octal literal validation.
646 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
647
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000648 // For harmony block scoping mode: Check if the scope has conflicting var/let
649 // declarations from different scopes. It covers for example
650 //
651 // function f() { { { var x; } let x; } }
652 // function g() { { var x; let x; } }
653 //
654 // The var declarations are hoisted to the function scope, but originate from
655 // a scope where the name has also been let bound or the var declaration is
656 // hoisted over such a scope.
657 void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
658
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000659 // Parser support
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000660 VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
661 FunctionLiteral* fun,
662 bool resolve,
663 bool* ok);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000664
665 bool TargetStackContainsLabel(Handle<String> label);
666 BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
667 IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
668
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000669 void RegisterTargetUse(Label* target, Target* stop);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000670
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000671 // Factory methods.
672
673 Statement* EmptyStatement() {
674 static v8::internal::EmptyStatement empty;
675 return &empty;
676 }
677
678 Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
679
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000680 Handle<String> LookupSymbol(int symbol_id);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000681
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000682 Handle<String> LookupCachedSymbol(int symbol_id);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000683
684 Expression* NewCall(Expression* expression,
685 ZoneList<Expression*>* arguments,
686 int pos) {
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000687 return new(zone()) Call(isolate(), expression, arguments, pos);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000688 }
689
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000690 inline Literal* NewLiteral(Handle<Object> handle) {
691 return new(zone()) Literal(isolate(), handle);
692 }
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000693
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000694 // Create a number literal.
695 Literal* NewNumberLiteral(double value);
696
697 // Generate AST node that throw a ReferenceError with the given type.
698 Expression* NewThrowReferenceError(Handle<String> type);
699
700 // Generate AST node that throw a SyntaxError with the given
701 // type. The first argument may be null (in the handle sense) in
702 // which case no arguments are passed to the constructor.
703 Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first);
704
705 // Generate AST node that throw a TypeError with the given
706 // type. Both arguments must be non-null (in the handle sense).
707 Expression* NewThrowTypeError(Handle<String> type,
708 Handle<Object> first,
709 Handle<Object> second);
710
711 // Generic AST generator for throwing errors from compiled code.
712 Expression* NewThrowError(Handle<String> constructor,
713 Handle<String> type,
714 Vector< Handle<Object> > arguments);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000715
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000716 Isolate* isolate_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000717 ZoneList<Handle<String> > symbol_cache_;
718
719 Handle<Script> script_;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000720 JavaScriptScanner scanner_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000721
722 Scope* top_scope_;
723 int with_nesting_level_;
724
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000725 LexicalScope* lexical_scope_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000726 Mode mode_;
727
728 Target* target_stack_; // for break, continue statements
729 bool allow_natives_syntax_;
730 v8::Extension* extension_;
731 bool is_pre_parsing_;
732 ScriptDataImpl* pre_data_;
733 FuncNameInferrer* fni_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000734 bool stack_overflow_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000735 // If true, the next (and immediately following) function literal is
736 // preceded by a parenthesis.
737 // Heuristically that means that the function will be called immediately,
738 // so never lazily compile it.
739 bool parenthesized_function_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000740 bool harmony_block_scoping_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000741
742 friend class LexicalScope;
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000743};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000744
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000745
746// Support for handling complex values (array and object literals) that
747// can be fully handled at compile time.
748class CompileTimeValue: public AllStatic {
749 public:
750 enum Type {
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000751 OBJECT_LITERAL_FAST_ELEMENTS,
752 OBJECT_LITERAL_SLOW_ELEMENTS,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000753 ARRAY_LITERAL
754 };
755
756 static bool IsCompileTimeValue(Expression* expression);
757
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000758 static bool ArrayLiteralElementNeedsInitialization(Expression* value);
759
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000760 // Get the value as a compile time value.
761 static Handle<FixedArray> GetValue(Expression* expression);
762
763 // Get the type of a compile time value returned by GetValue().
764 static Type GetType(Handle<FixedArray> value);
765
766 // Get the elements array of a compile time value returned by GetValue().
767 static Handle<FixedArray> GetElements(Handle<FixedArray> value);
768
769 private:
770 static const int kTypeSlot = 0;
771 static const int kElementsSlot = 1;
772
773 DISALLOW_IMPLICIT_CONSTRUCTORS(CompileTimeValue);
774};
775
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000776} } // namespace v8::internal
777
778#endif // V8_PARSER_H_