blob: 667410b3ce3e459da2862532c751bd1f7e4fcea9 [file] [log] [blame]
Ben Murdochf87a2032010-10-22 12:50:53 +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#ifndef V8_PARSER_H_
29#define V8_PARSER_H_
30
Steve Blocka7e24c12009-10-30 11:49:00 +000031#include "allocation.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010032#include "ast.h"
33#include "scanner.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080034#include "scopes.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035
36namespace v8 {
37namespace internal {
38
Ben Murdochf87a2032010-10-22 12:50:53 +010039class CompilationInfo;
40class FuncNameInferrer;
Ben Murdochf87a2032010-10-22 12:50:53 +010041class ParserLog;
42class PositionStack;
43class Target;
44class TemporaryScope;
45
46template <typename T> class ZoneListWrapper;
47
Steve Blocka7e24c12009-10-30 11:49:00 +000048
49class ParserMessage : public Malloced {
50 public:
51 ParserMessage(Scanner::Location loc, const char* message,
52 Vector<const char*> args)
53 : loc_(loc),
54 message_(message),
55 args_(args) { }
56 ~ParserMessage();
57 Scanner::Location location() { return loc_; }
58 const char* message() { return message_; }
59 Vector<const char*> args() { return args_; }
60 private:
61 Scanner::Location loc_;
62 const char* message_;
63 Vector<const char*> args_;
64};
65
66
67class FunctionEntry BASE_EMBEDDED {
68 public:
69 explicit FunctionEntry(Vector<unsigned> backing) : backing_(backing) { }
70 FunctionEntry() : backing_(Vector<unsigned>::empty()) { }
71
72 int start_pos() { return backing_[kStartPosOffset]; }
73 void set_start_pos(int value) { backing_[kStartPosOffset] = value; }
74
75 int end_pos() { return backing_[kEndPosOffset]; }
76 void set_end_pos(int value) { backing_[kEndPosOffset] = value; }
77
78 int literal_count() { return backing_[kLiteralCountOffset]; }
79 void set_literal_count(int value) { backing_[kLiteralCountOffset] = value; }
80
81 int property_count() { return backing_[kPropertyCountOffset]; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +010082 void set_property_count(int value) {
83 backing_[kPropertyCountOffset] = value;
84 }
85
Steve Blocka7e24c12009-10-30 11:49:00 +000086 bool is_valid() { return backing_.length() > 0; }
87
Ben Murdochf87a2032010-10-22 12:50:53 +010088 static const int kSize = 4;
Steve Blocka7e24c12009-10-30 11:49:00 +000089
90 private:
91 Vector<unsigned> backing_;
92 static const int kStartPosOffset = 0;
93 static const int kEndPosOffset = 1;
94 static const int kLiteralCountOffset = 2;
95 static const int kPropertyCountOffset = 3;
Steve Blocka7e24c12009-10-30 11:49:00 +000096};
97
98
99class ScriptDataImpl : public ScriptData {
100 public:
101 explicit ScriptDataImpl(Vector<unsigned> store)
102 : store_(store),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100103 owns_store_(true) { }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100104
105 // Create an empty ScriptDataImpl that is guaranteed to not satisfy
106 // a SanityCheck.
107 ScriptDataImpl() : store_(Vector<unsigned>()), owns_store_(false) { }
108
Steve Blocka7e24c12009-10-30 11:49:00 +0000109 virtual ~ScriptDataImpl();
110 virtual int Length();
Leon Clarkef7060e22010-06-03 12:02:55 +0100111 virtual const char* Data();
Leon Clarkee46be812010-01-19 14:06:41 +0000112 virtual bool HasError();
Iain Merrick9ac36c92010-09-13 15:29:50 +0100113
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100114 void Initialize();
115 void ReadNextSymbolPosition();
116
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100117 FunctionEntry GetFunctionEntry(int start);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100118 int GetSymbolIdentifier();
Steve Blocka7e24c12009-10-30 11:49:00 +0000119 bool SanityCheck();
120
121 Scanner::Location MessageLocation();
122 const char* BuildMessage();
123 Vector<const char*> BuildArgs();
124
Iain Merrick9ac36c92010-09-13 15:29:50 +0100125 int symbol_count() {
126 return (store_.length() > kHeaderSize) ? store_[kSymbolCountOffset] : 0;
127 }
128 // The following functions should only be called if SanityCheck has
129 // returned true.
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 bool has_error() { return store_[kHasErrorOffset]; }
131 unsigned magic() { return store_[kMagicOffset]; }
132 unsigned version() { return store_[kVersionOffset]; }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100133
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 static const unsigned kMagicNumber = 0xBadDead;
Ben Murdochf87a2032010-10-22 12:50:53 +0100135 static const unsigned kCurrentVersion = 4;
Steve Blocka7e24c12009-10-30 11:49:00 +0000136
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100137 static const int kMagicOffset = 0;
138 static const int kVersionOffset = 1;
139 static const int kHasErrorOffset = 2;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100140 static const int kFunctionsSizeOffset = 3;
141 static const int kSymbolCountOffset = 4;
142 static const int kSizeOffset = 5;
143 static const int kHeaderSize = 6;
144
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100145 // If encoding a message, the following positions are fixed.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100146 static const int kMessageStartPos = 0;
147 static const int kMessageEndPos = 1;
148 static const int kMessageArgCountPos = 2;
149 static const int kMessageTextPos = 3;
Steve Blocka7e24c12009-10-30 11:49:00 +0000150
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100151 static const byte kNumberTerminator = 0x80u;
152
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 private:
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100154 Vector<unsigned> store_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100155 unsigned char* symbol_data_;
156 unsigned char* symbol_data_end_;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100157 int function_index_;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100158 bool owns_store_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100159
Steve Blocka7e24c12009-10-30 11:49:00 +0000160 unsigned Read(int position);
161 unsigned* ReadAddress(int position);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100162 // Reads a number from the current symbols
163 int ReadNumber(byte** source);
Steve Blocka7e24c12009-10-30 11:49:00 +0000164
Iain Merrick9ac36c92010-09-13 15:29:50 +0100165 ScriptDataImpl(const char* backing_store, int length)
166 : store_(reinterpret_cast<unsigned*>(const_cast<char*>(backing_store)),
Ben Murdochf87a2032010-10-22 12:50:53 +0100167 length / static_cast<int>(sizeof(unsigned))),
Iain Merrick9ac36c92010-09-13 15:29:50 +0100168 owns_store_(false) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100169 ASSERT_EQ(0, static_cast<int>(
170 reinterpret_cast<intptr_t>(backing_store) % sizeof(unsigned)));
Iain Merrick9ac36c92010-09-13 15:29:50 +0100171 }
172
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100173 // Read strings written by ParserRecorder::WriteString.
174 static const char* ReadString(unsigned* start, int* chars);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100175
176 friend class ScriptData;
Steve Blocka7e24c12009-10-30 11:49:00 +0000177};
178
179
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800180// Record only functions.
181class PartialParserRecorder {
Ben Murdochf87a2032010-10-22 12:50:53 +0100182 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800183 PartialParserRecorder();
Steve Blocka7e24c12009-10-30 11:49:00 +0000184
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800185 void LogFunction(int start, int end, int literals, int properties) {
186 function_store_.Add(start);
187 function_store_.Add(end);
188 function_store_.Add(literals);
189 function_store_.Add(properties);
190 }
191
192 void LogSymbol(int start, const char* symbol, int length) { }
193
194 // Logs an error message and marks the log as containing an error.
195 // Further logging will be ignored, and ExtractData will return a vector
196 // representing the error only.
197 void LogMessage(int start,
198 int end,
199 const char* message,
200 const char* argument_opt) {
201 Scanner::Location location(start, end);
202 Vector<const char*> arguments;
203 if (argument_opt != NULL) {
204 arguments = Vector<const char*>(&argument_opt, 1);
205 }
206 this->LogMessage(location, message, arguments);
207 }
208
209 int function_position() { return function_store_.size(); }
210
211 void LogMessage(Scanner::Location loc,
212 const char* message,
213 Vector<const char*> args);
214
215 Vector<unsigned> ExtractData();
216
217 void PauseRecording() {
218 pause_count_++;
219 is_recording_ = false;
220 }
221
222 void ResumeRecording() {
223 ASSERT(pause_count_ > 0);
224 if (--pause_count_ == 0) is_recording_ = !has_error();
225 }
226
227 int symbol_position() { return 0; }
228 int symbol_ids() { return 0; }
229
230 protected:
231 bool has_error() {
232 return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
233 }
234
235 bool is_recording() {
236 return is_recording_;
237 }
238
239 void WriteString(Vector<const char> str);
240
241 Collector<unsigned> function_store_;
242 unsigned preamble_[ScriptDataImpl::kHeaderSize];
243 bool is_recording_;
244 int pause_count_;
245
246#ifdef DEBUG
247 int prev_start_;
248#endif
249};
250
251
252// Record both functions and symbols.
253class CompleteParserRecorder: public PartialParserRecorder {
254 public:
255 CompleteParserRecorder();
256
257 void LogSymbol(int start, Vector<const char> literal);
258
259 void LogSymbol(int start, const char* symbol, int length) {
260 LogSymbol(start, Vector<const char>(symbol, length));
261 }
262
263 Vector<unsigned> ExtractData();
264
265 int symbol_position() { return symbol_store_.size(); }
266 int symbol_ids() { return symbol_id_; }
267
268 private:
269 static int vector_hash(Vector<const char> string) {
270 int hash = 0;
271 for (int i = 0; i < string.length(); i++) {
272 int c = string[i];
273 hash += c;
274 hash += (hash << 10);
275 hash ^= (hash >> 6);
276 }
277 return hash;
278 }
279
280 static bool vector_compare(void* a, void* b) {
281 Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
282 Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b);
283 int length = string1->length();
284 if (string2->length() != length) return false;
285 return memcmp(string1->start(), string2->start(), length) == 0;
286 }
287
288 // Write a non-negative number to the symbol store.
289 void WriteNumber(int number);
290
291 Collector<byte> symbol_store_;
292 Collector<Vector<const char> > symbol_entries_;
293 HashMap symbol_table_;
294 int symbol_id_;
295};
296
297
298
299class ParserApi {
300 public:
Ben Murdochf87a2032010-10-22 12:50:53 +0100301 // Parses the source code represented by the compilation info and sets its
302 // function literal. Returns false (and deallocates any allocated AST
303 // nodes) if parsing failed.
304 static bool Parse(CompilationInfo* info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
Ben Murdochf87a2032010-10-22 12:50:53 +0100306 // Generic preparser generating full preparse data.
307 static ScriptDataImpl* PreParse(Handle<String> source,
308 unibrow::CharacterStream* stream,
309 v8::Extension* extension);
310
311 // Preparser that only does preprocessing that makes sense if only used
312 // immediately after.
313 static ScriptDataImpl* PartialPreParse(Handle<String> source,
314 unibrow::CharacterStream* stream,
315 v8::Extension* extension);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800316};
317
318// ----------------------------------------------------------------------------
319// REGEXP PARSING
320
321// A BuffferedZoneList is an automatically growing list, just like (and backed
322// by) a ZoneList, that is optimized for the case of adding and removing
323// a single element. The last element added is stored outside the backing list,
324// and if no more than one element is ever added, the ZoneList isn't even
325// allocated.
326// Elements must not be NULL pointers.
327template <typename T, int initial_size>
328class BufferedZoneList {
329 public:
330 BufferedZoneList() : list_(NULL), last_(NULL) {}
331
332 // Adds element at end of list. This element is buffered and can
333 // be read using last() or removed using RemoveLast until a new Add or until
334 // RemoveLast or GetList has been called.
335 void Add(T* value) {
336 if (last_ != NULL) {
337 if (list_ == NULL) {
338 list_ = new ZoneList<T*>(initial_size);
339 }
340 list_->Add(last_);
341 }
342 last_ = value;
343 }
344
345 T* last() {
346 ASSERT(last_ != NULL);
347 return last_;
348 }
349
350 T* RemoveLast() {
351 ASSERT(last_ != NULL);
352 T* result = last_;
353 if ((list_ != NULL) && (list_->length() > 0))
354 last_ = list_->RemoveLast();
355 else
356 last_ = NULL;
357 return result;
358 }
359
360 T* Get(int i) {
361 ASSERT((0 <= i) && (i < length()));
362 if (list_ == NULL) {
363 ASSERT_EQ(0, i);
364 return last_;
365 } else {
366 if (i == list_->length()) {
367 ASSERT(last_ != NULL);
368 return last_;
369 } else {
370 return list_->at(i);
371 }
372 }
373 }
374
375 void Clear() {
376 list_ = NULL;
377 last_ = NULL;
378 }
379
380 int length() {
381 int length = (list_ == NULL) ? 0 : list_->length();
382 return length + ((last_ == NULL) ? 0 : 1);
383 }
384
385 ZoneList<T*>* GetList() {
386 if (list_ == NULL) {
387 list_ = new ZoneList<T*>(initial_size);
388 }
389 if (last_ != NULL) {
390 list_->Add(last_);
391 last_ = NULL;
392 }
393 return list_;
394 }
395
396 private:
397 ZoneList<T*>* list_;
398 T* last_;
399};
400
401
402// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
403class RegExpBuilder: public ZoneObject {
404 public:
405 RegExpBuilder();
406 void AddCharacter(uc16 character);
407 // "Adds" an empty expression. Does nothing except consume a
408 // following quantifier
409 void AddEmpty();
410 void AddAtom(RegExpTree* tree);
411 void AddAssertion(RegExpTree* tree);
412 void NewAlternative(); // '|'
413 void AddQuantifierToAtom(int min, int max, RegExpQuantifier::Type type);
414 RegExpTree* ToRegExp();
415
416 private:
417 void FlushCharacters();
418 void FlushText();
419 void FlushTerms();
420 bool pending_empty_;
421 ZoneList<uc16>* characters_;
422 BufferedZoneList<RegExpTree, 2> terms_;
423 BufferedZoneList<RegExpTree, 2> text_;
424 BufferedZoneList<RegExpTree, 2> alternatives_;
425#ifdef DEBUG
426 enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_;
427#define LAST(x) last_added_ = x;
428#else
429#define LAST(x)
430#endif
431};
432
433
434class RegExpParser {
435 public:
436 RegExpParser(FlatStringReader* in,
437 Handle<String>* error,
438 bool multiline_mode);
Ben Murdochf87a2032010-10-22 12:50:53 +0100439
440 static bool ParseRegExp(FlatStringReader* input,
441 bool multiline,
442 RegExpCompileData* result);
443
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800444 RegExpTree* ParsePattern();
445 RegExpTree* ParseDisjunction();
446 RegExpTree* ParseGroup();
447 RegExpTree* ParseCharacterClass();
Ben Murdochf87a2032010-10-22 12:50:53 +0100448
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800449 // Parses a {...,...} quantifier and stores the range in the given
450 // out parameters.
451 bool ParseIntervalQuantifier(int* min_out, int* max_out);
Steve Block59151502010-09-22 15:07:15 +0100452
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800453 // Parses and returns a single escaped character. The character
454 // must not be 'b' or 'B' since they are usually handle specially.
455 uc32 ParseClassCharacterEscape();
456
457 // Checks whether the following is a length-digit hexadecimal number,
458 // and sets the value if it is.
459 bool ParseHexEscape(int length, uc32* value);
460
461 uc32 ParseControlLetterEscape();
462 uc32 ParseOctalLiteral();
463
464 // Tries to parse the input as a back reference. If successful it
465 // stores the result in the output parameter and returns true. If
466 // it fails it will push back the characters read so the same characters
467 // can be reparsed.
468 bool ParseBackReferenceIndex(int* index_out);
469
470 CharacterRange ParseClassAtom(uc16* char_class);
471 RegExpTree* ReportError(Vector<const char> message);
472 void Advance();
473 void Advance(int dist);
474 void Reset(int pos);
475
476 // Reports whether the pattern might be used as a literal search string.
477 // Only use if the result of the parse is a single atom node.
478 bool simple();
479 bool contains_anchor() { return contains_anchor_; }
480 void set_contains_anchor() { contains_anchor_ = true; }
481 int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
482 int position() { return next_pos_ - 1; }
483 bool failed() { return failed_; }
484
485 static const int kMaxCaptures = 1 << 16;
486 static const uc32 kEndMarker = (1 << 21);
487
488 private:
489 enum SubexpressionType {
490 INITIAL,
491 CAPTURE, // All positive values represent captures.
492 POSITIVE_LOOKAHEAD,
493 NEGATIVE_LOOKAHEAD,
494 GROUPING
495 };
496
497 class RegExpParserState : public ZoneObject {
498 public:
499 RegExpParserState(RegExpParserState* previous_state,
500 SubexpressionType group_type,
501 int disjunction_capture_index)
502 : previous_state_(previous_state),
503 builder_(new RegExpBuilder()),
504 group_type_(group_type),
505 disjunction_capture_index_(disjunction_capture_index) {}
506 // Parser state of containing expression, if any.
507 RegExpParserState* previous_state() { return previous_state_; }
508 bool IsSubexpression() { return previous_state_ != NULL; }
509 // RegExpBuilder building this regexp's AST.
510 RegExpBuilder* builder() { return builder_; }
511 // Type of regexp being parsed (parenthesized group or entire regexp).
512 SubexpressionType group_type() { return group_type_; }
513 // Index in captures array of first capture in this sub-expression, if any.
514 // Also the capture index of this sub-expression itself, if group_type
515 // is CAPTURE.
516 int capture_index() { return disjunction_capture_index_; }
517
518 private:
519 // Linked list implementation of stack of states.
520 RegExpParserState* previous_state_;
521 // Builder for the stored disjunction.
522 RegExpBuilder* builder_;
523 // Stored disjunction type (capture, look-ahead or grouping), if any.
524 SubexpressionType group_type_;
525 // Stored disjunction's capture index (if any).
526 int disjunction_capture_index_;
527 };
528
529 uc32 current() { return current_; }
530 bool has_more() { return has_more_; }
531 bool has_next() { return next_pos_ < in()->length(); }
532 uc32 Next();
533 FlatStringReader* in() { return in_; }
534 void ScanForCaptures();
535
536 Handle<String>* error_;
537 ZoneList<RegExpCapture*>* captures_;
538 FlatStringReader* in_;
539 uc32 current_;
540 int next_pos_;
541 // The capture count is only valid after we have scanned for captures.
542 int capture_count_;
543 bool has_more_;
544 bool multiline_;
545 bool simple_;
546 bool contains_anchor_;
547 bool is_scanned_for_captures_;
548 bool failed_;
549};
550
551// ----------------------------------------------------------------------------
552// JAVASCRIPT PARSING
553
554class Parser {
555 public:
556 Parser(Handle<Script> script,
557 bool allow_natives_syntax,
558 v8::Extension* extension,
559 ScriptDataImpl* pre_data);
560 virtual ~Parser() { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000561
Ben Murdochf87a2032010-10-22 12:50:53 +0100562 // Returns NULL if parsing failed.
563 FunctionLiteral* ParseProgram(Handle<String> source,
564 bool in_global_context);
Ben Murdochf87a2032010-10-22 12:50:53 +0100565
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800566 FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
567
568 void ReportMessageAt(Scanner::Location loc,
569 const char* message,
570 Vector<const char*> args);
Ben Murdochf87a2032010-10-22 12:50:53 +0100571
572 protected:
Ben Murdochf87a2032010-10-22 12:50:53 +0100573 enum Mode {
574 PARSE_LAZILY,
575 PARSE_EAGERLY
576 };
577
578 // Report syntax error
579 void ReportUnexpectedToken(Token::Value token);
580 void ReportInvalidPreparseData(Handle<String> name, bool* ok);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800581 void ReportMessage(const char* message, Vector<const char*> args);
Ben Murdochf87a2032010-10-22 12:50:53 +0100582
583 bool inside_with() const { return with_nesting_level_ > 0; }
Ben Murdochf87a2032010-10-22 12:50:53 +0100584 Scanner& scanner() { return scanner_; }
585 Mode mode() const { return mode_; }
586 ScriptDataImpl* pre_data() const { return pre_data_; }
587
588 // All ParseXXX functions take as the last argument an *ok parameter
589 // which is set to false if parsing failed; it is unchanged otherwise.
590 // By making the 'exception handling' explicit, we are forced to check
591 // for failure at the call sites.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800592 void* ParseSourceElements(ZoneList<Statement*>* processor,
Ben Murdochf87a2032010-10-22 12:50:53 +0100593 int end_token, bool* ok);
594 Statement* ParseStatement(ZoneStringList* labels, bool* ok);
595 Statement* ParseFunctionDeclaration(bool* ok);
596 Statement* ParseNativeDeclaration(bool* ok);
597 Block* ParseBlock(ZoneStringList* labels, bool* ok);
598 Block* ParseVariableStatement(bool* ok);
599 Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok);
600 Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
601 bool* ok);
602 IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
603 Statement* ParseContinueStatement(bool* ok);
604 Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
605 Statement* ParseReturnStatement(bool* ok);
606 Block* WithHelper(Expression* obj,
607 ZoneStringList* labels,
608 bool is_catch_block,
609 bool* ok);
610 Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
611 CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
612 SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
613 DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
614 WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
615 Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
616 Statement* ParseThrowStatement(bool* ok);
617 Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
618 TryStatement* ParseTryStatement(bool* ok);
619 DebuggerStatement* ParseDebuggerStatement(bool* ok);
620
621 Expression* ParseExpression(bool accept_IN, bool* ok);
622 Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
623 Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
624 Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
625 Expression* ParseUnaryExpression(bool* ok);
626 Expression* ParsePostfixExpression(bool* ok);
627 Expression* ParseLeftHandSideExpression(bool* ok);
628 Expression* ParseNewExpression(bool* ok);
629 Expression* ParseMemberExpression(bool* ok);
630 Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
631 Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
632 bool* ok);
633 Expression* ParsePrimaryExpression(bool* ok);
634 Expression* ParseArrayLiteral(bool* ok);
635 Expression* ParseObjectLiteral(bool* ok);
636 ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok);
637 Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
638
639 Expression* NewCompareNode(Token::Value op,
640 Expression* x,
641 Expression* y,
642 int position);
643
644 // Populate the constant properties fixed array for a materialized object
645 // literal.
646 void BuildObjectLiteralConstantProperties(
647 ZoneList<ObjectLiteral::Property*>* properties,
648 Handle<FixedArray> constants,
649 bool* is_simple,
650 bool* fast_elements,
651 int* depth);
652
653 // Populate the literals fixed array for a materialized array literal.
654 void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties,
655 Handle<FixedArray> constants,
656 bool* is_simple,
657 int* depth);
658
659 // Decide if a property should be in the object boilerplate.
660 bool IsBoilerplateProperty(ObjectLiteral::Property* property);
661 // If the expression is a literal, return the literal value;
662 // if the expression is a materialized literal and is simple return a
663 // compile time value as encoded by CompileTimeValue::GetValue().
664 // Otherwise, return undefined literal as the placeholder
665 // in the object literal boilerplate.
666 Handle<Object> GetBoilerplateValue(Expression* expression);
667
668 enum FunctionLiteralType {
669 EXPRESSION,
670 DECLARATION,
671 NESTED
672 };
673
674 ZoneList<Expression*>* ParseArguments(bool* ok);
675 FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
676 int function_token_position,
677 FunctionLiteralType type,
678 bool* ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000679
680
Ben Murdochf87a2032010-10-22 12:50:53 +0100681 // Magical syntax support.
682 Expression* ParseV8Intrinsic(bool* ok);
683
684 INLINE(Token::Value peek()) { return scanner_.peek(); }
685 INLINE(Token::Value Next()) { return scanner_.Next(); }
686 INLINE(void Consume(Token::Value token));
687 void Expect(Token::Value token, bool* ok);
688 bool Check(Token::Value token);
689 void ExpectSemicolon(bool* ok);
690
691 Handle<String> GetSymbol(bool* ok);
692
693 // Get odd-ball literals.
694 Literal* GetLiteralUndefined();
695 Literal* GetLiteralTheHole();
696 Literal* GetLiteralNumber(double value);
697
698 Handle<String> ParseIdentifier(bool* ok);
699 Handle<String> ParseIdentifierName(bool* ok);
700 Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
701 bool* is_set,
702 bool* ok);
703
704 // Parser support
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800705 VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
706 FunctionLiteral* fun,
707 bool resolve,
708 bool* ok);
Ben Murdochf87a2032010-10-22 12:50:53 +0100709
710 bool TargetStackContainsLabel(Handle<String> label);
711 BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
712 IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
713
714 void RegisterTargetUse(BreakTarget* target, Target* stop);
715
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800716 // Factory methods.
717
718 Statement* EmptyStatement() {
719 static v8::internal::EmptyStatement empty;
720 return &empty;
721 }
722
723 Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
724
725 Handle<String> LookupSymbol(int symbol_id,
726 Vector<const char> string);
727
728 Handle<String> LookupCachedSymbol(int symbol_id,
729 Vector<const char> string);
730
731 Expression* NewCall(Expression* expression,
732 ZoneList<Expression*>* arguments,
733 int pos) {
734 return new Call(expression, arguments, pos);
735 }
736
737
Ben Murdochf87a2032010-10-22 12:50:53 +0100738 // Create a number literal.
739 Literal* NewNumberLiteral(double value);
740
741 // Generate AST node that throw a ReferenceError with the given type.
742 Expression* NewThrowReferenceError(Handle<String> type);
743
744 // Generate AST node that throw a SyntaxError with the given
745 // type. The first argument may be null (in the handle sense) in
746 // which case no arguments are passed to the constructor.
747 Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first);
748
749 // Generate AST node that throw a TypeError with the given
750 // type. Both arguments must be non-null (in the handle sense).
751 Expression* NewThrowTypeError(Handle<String> type,
752 Handle<Object> first,
753 Handle<Object> second);
754
755 // Generic AST generator for throwing errors from compiled code.
756 Expression* NewThrowError(Handle<String> constructor,
757 Handle<String> type,
758 Vector< Handle<Object> > arguments);
759
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800760 ZoneList<Handle<String> > symbol_cache_;
Ben Murdochf87a2032010-10-22 12:50:53 +0100761
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800762 Handle<Script> script_;
763 Scanner scanner_;
Ben Murdochf87a2032010-10-22 12:50:53 +0100764
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800765 Scope* top_scope_;
766 int with_nesting_level_;
Ben Murdochf87a2032010-10-22 12:50:53 +0100767
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800768 TemporaryScope* temp_scope_;
769 Mode mode_;
770
771 Target* target_stack_; // for break, continue statements
772 bool allow_natives_syntax_;
773 v8::Extension* extension_;
774 bool is_pre_parsing_;
775 ScriptDataImpl* pre_data_;
776 FuncNameInferrer* fni_;
Ben Murdochf87a2032010-10-22 12:50:53 +0100777};
Steve Blocka7e24c12009-10-30 11:49:00 +0000778
779
780// Support for handling complex values (array and object literals) that
781// can be fully handled at compile time.
782class CompileTimeValue: public AllStatic {
783 public:
784 enum Type {
Steve Block6ded16b2010-05-10 14:33:55 +0100785 OBJECT_LITERAL_FAST_ELEMENTS,
786 OBJECT_LITERAL_SLOW_ELEMENTS,
Steve Blocka7e24c12009-10-30 11:49:00 +0000787 ARRAY_LITERAL
788 };
789
790 static bool IsCompileTimeValue(Expression* expression);
791
Iain Merrick75681382010-08-19 15:07:18 +0100792 static bool ArrayLiteralElementNeedsInitialization(Expression* value);
793
Steve Blocka7e24c12009-10-30 11:49:00 +0000794 // Get the value as a compile time value.
795 static Handle<FixedArray> GetValue(Expression* expression);
796
797 // Get the type of a compile time value returned by GetValue().
798 static Type GetType(Handle<FixedArray> value);
799
800 // Get the elements array of a compile time value returned by GetValue().
801 static Handle<FixedArray> GetElements(Handle<FixedArray> value);
802
803 private:
804 static const int kTypeSlot = 0;
805 static const int kElementsSlot = 1;
806
807 DISALLOW_IMPLICIT_CONSTRUCTORS(CompileTimeValue);
808};
809
810
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800811// ----------------------------------------------------------------------------
812// JSON PARSING
813
814// JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
815// specification section 15.12.1 (and appendix A.8).
816// The grammar is given section 15.12.1.2 (and appendix A.8.2).
817class JsonParser BASE_EMBEDDED {
818 public:
819 // Parse JSON input as a single JSON value.
820 // Returns null handle and sets exception if parsing failed.
821 static Handle<Object> Parse(Handle<String> source) {
822 return JsonParser().ParseJson(source);
823 }
824
825 private:
826 JsonParser() { }
827 ~JsonParser() { }
828
829 // Parse a string containing a single JSON value.
830 Handle<Object> ParseJson(Handle<String>);
831 // Parse a single JSON value from input (grammar production JSONValue).
832 // A JSON value is either a (double-quoted) string literal, a number literal,
833 // one of "true", "false", or "null", or an object or array literal.
834 Handle<Object> ParseJsonValue();
835 // Parse a JSON object literal (grammar production JSONObject).
836 // An object literal is a squiggly-braced and comma separated sequence
837 // (possibly empty) of key/value pairs, where the key is a JSON string
838 // literal, the value is a JSON value, and the two are separated by a colon.
839 // A JSON array dosn't allow numbers and identifiers as keys, like a
840 // JavaScript array.
841 Handle<Object> ParseJsonObject();
842 // Parses a JSON array literal (grammar production JSONArray). An array
843 // literal is a square-bracketed and comma separated sequence (possibly empty)
844 // of JSON values.
845 // A JSON array doesn't allow leaving out values from the sequence, nor does
846 // it allow a terminal comma, like a JavaScript array does.
847 Handle<Object> ParseJsonArray();
848
849 // Mark that a parsing error has happened at the current token, and
850 // return a null handle. Primarily for readability.
851 Handle<Object> ReportUnexpectedToken() { return Handle<Object>::null(); }
852 // Converts the currently parsed literal to a JavaScript String.
853 Handle<String> GetString();
854
855 Scanner scanner_;
856};
Steve Blocka7e24c12009-10-30 11:49:00 +0000857} } // namespace v8::internal
858
859#endif // V8_PARSER_H_