Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/preparser.h

Issue 181453002: Reset trunk to 3.24.35.4 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/preparse-data.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifndef V8_PREPARSER_H 28 #ifndef V8_PREPARSER_H
29 #define V8_PREPARSER_H 29 #define V8_PREPARSER_H
30 30
31 #include "hashmap.h" 31 #include "hashmap.h"
32 #include "scopes.h"
33 #include "token.h" 32 #include "token.h"
34 #include "scanner.h" 33 #include "scanner.h"
35 #include "v8.h"
36 34
37 namespace v8 { 35 namespace v8 {
38 namespace internal { 36 namespace internal {
39 37
40 // Common base class shared between parser and pre-parser. 38 // Common base class shared between parser and pre-parser.
41 template <typename Traits> 39 class ParserBase {
42 class ParserBase : public Traits {
43 public: 40 public:
44 ParserBase(Scanner* scanner, uintptr_t stack_limit, 41 ParserBase(Scanner* scanner, uintptr_t stack_limit)
45 v8::Extension* extension, 42 : scanner_(scanner),
46 typename Traits::Type::Zone* zone,
47 typename Traits::Type::Parser this_object)
48 : Traits(this_object),
49 parenthesized_function_(false),
50 scope_(NULL),
51 function_state_(NULL),
52 extension_(extension),
53 scanner_(scanner),
54 stack_limit_(stack_limit), 43 stack_limit_(stack_limit),
55 stack_overflow_(false), 44 stack_overflow_(false),
56 allow_lazy_(false), 45 allow_lazy_(false),
57 allow_natives_syntax_(false), 46 allow_natives_syntax_(false),
58 allow_generators_(false), 47 allow_generators_(false),
59 allow_for_of_(false), 48 allow_for_of_(false) { }
60 zone_(zone) { } 49 // TODO(mstarzinger): Only virtual until message reporting has been unified.
50 virtual ~ParserBase() { }
61 51
62 // Getters that indicate whether certain syntactical constructs are 52 // Getters that indicate whether certain syntactical constructs are
63 // allowed to be parsed by this instance of the parser. 53 // allowed to be parsed by this instance of the parser.
64 bool allow_lazy() const { return allow_lazy_; } 54 bool allow_lazy() const { return allow_lazy_; }
65 bool allow_natives_syntax() const { return allow_natives_syntax_; } 55 bool allow_natives_syntax() const { return allow_natives_syntax_; }
66 bool allow_generators() const { return allow_generators_; } 56 bool allow_generators() const { return allow_generators_; }
67 bool allow_for_of() const { return allow_for_of_; } 57 bool allow_for_of() const { return allow_for_of_; }
68 bool allow_modules() const { return scanner()->HarmonyModules(); } 58 bool allow_modules() const { return scanner()->HarmonyModules(); }
69 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } 59 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
70 bool allow_harmony_numeric_literals() const { 60 bool allow_harmony_numeric_literals() const {
(...skipping 13 matching lines...) Expand all
84 void set_allow_harmony_numeric_literals(bool allow) { 74 void set_allow_harmony_numeric_literals(bool allow) {
85 scanner()->SetHarmonyNumericLiterals(allow); 75 scanner()->SetHarmonyNumericLiterals(allow);
86 } 76 }
87 77
88 protected: 78 protected:
89 enum AllowEvalOrArgumentsAsIdentifier { 79 enum AllowEvalOrArgumentsAsIdentifier {
90 kAllowEvalOrArguments, 80 kAllowEvalOrArguments,
91 kDontAllowEvalOrArguments 81 kDontAllowEvalOrArguments
92 }; 82 };
93 83
94 // ---------------------------------------------------------------------------
95 // FunctionState and BlockState together implement the parser's scope stack.
96 // The parser's current scope is in scope_. BlockState and FunctionState
97 // constructors push on the scope stack and the destructors pop. They are also
98 // used to hold the parser's per-function and per-block state.
99 class BlockState BASE_EMBEDDED {
100 public:
101 BlockState(typename Traits::Type::Scope** scope_stack,
102 typename Traits::Type::Scope* scope)
103 : scope_stack_(scope_stack),
104 outer_scope_(*scope_stack),
105 scope_(scope) {
106 *scope_stack_ = scope_;
107 }
108 ~BlockState() { *scope_stack_ = outer_scope_; }
109
110 private:
111 typename Traits::Type::Scope** scope_stack_;
112 typename Traits::Type::Scope* outer_scope_;
113 typename Traits::Type::Scope* scope_;
114 };
115
116 class FunctionState BASE_EMBEDDED {
117 public:
118 FunctionState(
119 FunctionState** function_state_stack,
120 typename Traits::Type::Scope** scope_stack,
121 typename Traits::Type::Scope* scope,
122 typename Traits::Type::Zone* zone = NULL);
123 ~FunctionState();
124
125 int NextMaterializedLiteralIndex() {
126 return next_materialized_literal_index_++;
127 }
128 int materialized_literal_count() {
129 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
130 }
131
132 int NextHandlerIndex() { return next_handler_index_++; }
133 int handler_count() { return next_handler_index_; }
134
135 void AddProperty() { expected_property_count_++; }
136 int expected_property_count() { return expected_property_count_; }
137
138 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
139 bool is_generator() const { return is_generator_; }
140
141 void set_generator_object_variable(
142 typename Traits::Type::GeneratorVariable* variable) {
143 ASSERT(variable != NULL);
144 ASSERT(!is_generator());
145 generator_object_variable_ = variable;
146 is_generator_ = true;
147 }
148 typename Traits::Type::GeneratorVariable* generator_object_variable()
149 const {
150 return generator_object_variable_;
151 }
152
153 typename Traits::Type::Factory* factory() { return &factory_; }
154
155 private:
156 // Used to assign an index to each literal that needs materialization in
157 // the function. Includes regexp literals, and boilerplate for object and
158 // array literals.
159 int next_materialized_literal_index_;
160
161 // Used to assign a per-function index to try and catch handlers.
162 int next_handler_index_;
163
164 // Properties count estimation.
165 int expected_property_count_;
166
167 // Whether the function is a generator.
168 bool is_generator_;
169 // For generators, this variable may hold the generator object. It variable
170 // is used by yield expressions and return statements. It is not necessary
171 // for generator functions to have this variable set.
172 Variable* generator_object_variable_;
173
174 FunctionState** function_state_stack_;
175 FunctionState* outer_function_state_;
176 typename Traits::Type::Scope** scope_stack_;
177 typename Traits::Type::Scope* outer_scope_;
178 Isolate* isolate_; // Only used by ParserTraits.
179 int saved_ast_node_id_; // Only used by ParserTraits.
180 typename Traits::Type::Factory factory_;
181
182 friend class ParserTraits;
183 };
184
185 Scanner* scanner() const { return scanner_; } 84 Scanner* scanner() const { return scanner_; }
186 int position() { return scanner_->location().beg_pos; } 85 int position() { return scanner_->location().beg_pos; }
187 int peek_position() { return scanner_->peek_location().beg_pos; } 86 int peek_position() { return scanner_->peek_location().beg_pos; }
188 bool stack_overflow() const { return stack_overflow_; } 87 bool stack_overflow() const { return stack_overflow_; }
189 void set_stack_overflow() { stack_overflow_ = true; } 88 void set_stack_overflow() { stack_overflow_ = true; }
190 typename Traits::Type::Zone* zone() const { return zone_; } 89
90 virtual bool is_classic_mode() = 0;
191 91
192 INLINE(Token::Value peek()) { 92 INLINE(Token::Value peek()) {
193 if (stack_overflow_) return Token::ILLEGAL; 93 if (stack_overflow_) return Token::ILLEGAL;
194 return scanner()->peek(); 94 return scanner()->peek();
195 } 95 }
196 96
197 INLINE(Token::Value Next()) { 97 INLINE(Token::Value Next()) {
198 if (stack_overflow_) return Token::ILLEGAL; 98 if (stack_overflow_) return Token::ILLEGAL;
199 { 99 {
200 int marker; 100 int marker;
(...skipping 24 matching lines...) Expand all
225 } 125 }
226 126
227 void Expect(Token::Value token, bool* ok) { 127 void Expect(Token::Value token, bool* ok) {
228 Token::Value next = Next(); 128 Token::Value next = Next();
229 if (next != token) { 129 if (next != token) {
230 ReportUnexpectedToken(next); 130 ReportUnexpectedToken(next);
231 *ok = false; 131 *ok = false;
232 } 132 }
233 } 133 }
234 134
235 void ExpectSemicolon(bool* ok) { 135 bool peek_any_identifier();
236 // Check for automatic semicolon insertion according to 136 void ExpectSemicolon(bool* ok);
237 // the rules given in ECMA-262, section 7.9, page 21. 137 bool CheckContextualKeyword(Vector<const char> keyword);
238 Token::Value tok = peek(); 138 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok);
239 if (tok == Token::SEMICOLON) {
240 Next();
241 return;
242 }
243 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
244 tok == Token::RBRACE ||
245 tok == Token::EOS) {
246 return;
247 }
248 Expect(Token::SEMICOLON, ok);
249 }
250 139
251 bool peek_any_identifier() { 140 // Strict mode octal literal validation.
252 Token::Value next = peek(); 141 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
253 return next == Token::IDENTIFIER ||
254 next == Token::FUTURE_RESERVED_WORD ||
255 next == Token::FUTURE_STRICT_RESERVED_WORD ||
256 next == Token::YIELD;
257 }
258
259 bool CheckContextualKeyword(Vector<const char> keyword) {
260 if (peek() == Token::IDENTIFIER &&
261 scanner()->is_next_contextual_keyword(keyword)) {
262 Consume(Token::IDENTIFIER);
263 return true;
264 }
265 return false;
266 }
267
268 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
269 Expect(Token::IDENTIFIER, ok);
270 if (!*ok) return;
271 if (!scanner()->is_literal_contextual_keyword(keyword)) {
272 ReportUnexpectedToken(scanner()->current_token());
273 *ok = false;
274 }
275 }
276
277 // Checks whether an octal literal was last seen between beg_pos and end_pos.
278 // If so, reports an error. Only called for strict mode.
279 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
280 Scanner::Location octal = scanner()->octal_position();
281 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
282 octal.end_pos <= end_pos) {
283 ReportMessageAt(octal, "strict_octal_literal");
284 scanner()->clear_octal_position();
285 *ok = false;
286 }
287 }
288 142
289 // Determine precedence of given token. 143 // Determine precedence of given token.
290 static int Precedence(Token::Value token, bool accept_IN) { 144 static int Precedence(Token::Value token, bool accept_IN);
291 if (token == Token::IN && !accept_IN)
292 return 0; // 0 precedence will terminate binary expression parsing
293 return Token::Precedence(token);
294 }
295
296 typename Traits::Type::Factory* factory() {
297 return function_state_->factory();
298 }
299
300 bool is_classic_mode() const { return scope_->is_classic_mode(); }
301
302 bool is_generator() const { return function_state_->is_generator(); }
303 145
304 // Report syntax errors. 146 // Report syntax errors.
305 void ReportMessage(const char* message, Vector<const char*> args) { 147 void ReportUnexpectedToken(Token::Value token);
306 Scanner::Location source_location = scanner()->location(); 148 void ReportMessageAt(Scanner::Location location, const char* type) {
307 Traits::ReportMessageAt(source_location, message, args); 149 ReportMessageAt(location, type, Vector<const char*>::empty());
308 } 150 }
309 151 virtual void ReportMessageAt(Scanner::Location source_location,
310 void ReportMessageAt(Scanner::Location location, const char* message) { 152 const char* message,
311 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); 153 Vector<const char*> args) = 0;
312 }
313
314 void ReportUnexpectedToken(Token::Value token);
315
316 // Recursive descent functions:
317
318 // Parses an identifier that is valid for the current scope, in particular it
319 // fails on strict mode future reserved keywords in a strict scope. If
320 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
321 // "arguments" as identifier even in strict mode (this is needed in cases like
322 // "var foo = eval;").
323 typename Traits::Type::Identifier ParseIdentifier(
324 AllowEvalOrArgumentsAsIdentifier,
325 bool* ok);
326 // Parses an identifier or a strict mode future reserved word, and indicate
327 // whether it is strict mode future reserved.
328 typename Traits::Type::Identifier ParseIdentifierOrStrictReservedWord(
329 bool* is_strict_reserved,
330 bool* ok);
331 typename Traits::Type::Identifier ParseIdentifierName(bool* ok);
332 // Parses an identifier and determines whether or not it is 'get' or 'set'.
333 typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
334 bool* is_set,
335 bool* ok);
336
337 typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal,
338 bool* ok);
339
340 typename Traits::Type::Expression ParsePrimaryExpression(bool* ok);
341 typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok);
342 typename Traits::Type::Expression ParseArrayLiteral(bool* ok);
343 154
344 // Used to detect duplicates in object literals. Each of the values 155 // Used to detect duplicates in object literals. Each of the values
345 // kGetterProperty, kSetterProperty and kValueProperty represents 156 // kGetterProperty, kSetterProperty and kValueProperty represents
346 // a type of object literal property. When parsing a property, its 157 // a type of object literal property. When parsing a property, its
347 // type value is stored in the DuplicateFinder for the property name. 158 // type value is stored in the DuplicateFinder for the property name.
348 // Values are chosen so that having intersection bits means the there is 159 // Values are chosen so that having intersection bits means the there is
349 // an incompatibility. 160 // an incompatibility.
350 // I.e., you can add a getter to a property that already has a setter, since 161 // I.e., you can add a getter to a property that already has a setter, since
351 // kGetterProperty and kSetterProperty doesn't intersect, but not if it 162 // kGetterProperty and kSetterProperty doesn't intersect, but not if it
352 // already has a getter or a value. Adding the getter to an existing 163 // already has a getter or a value. Adding the getter to an existing
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 } 199 }
389 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { 200 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
390 return ((type1 | type2) & kValueFlag) == 0; 201 return ((type1 | type2) & kValueFlag) == 0;
391 } 202 }
392 203
393 ParserBase* parser_; 204 ParserBase* parser_;
394 DuplicateFinder finder_; 205 DuplicateFinder finder_;
395 LanguageMode language_mode_; 206 LanguageMode language_mode_;
396 }; 207 };
397 208
398 // If true, the next (and immediately following) function literal is
399 // preceded by a parenthesis.
400 // Heuristically that means that the function will be called immediately,
401 // so never lazily compile it.
402 bool parenthesized_function_;
403
404 typename Traits::Type::Scope* scope_; // Scope stack.
405 FunctionState* function_state_; // Function state stack.
406 v8::Extension* extension_;
407
408 private: 209 private:
409 Scanner* scanner_; 210 Scanner* scanner_;
410 uintptr_t stack_limit_; 211 uintptr_t stack_limit_;
411 bool stack_overflow_; 212 bool stack_overflow_;
412 213
413 bool allow_lazy_; 214 bool allow_lazy_;
414 bool allow_natives_syntax_; 215 bool allow_natives_syntax_;
415 bool allow_generators_; 216 bool allow_generators_;
416 bool allow_for_of_; 217 bool allow_for_of_;
417
418 typename Traits::Type::Zone* zone_; // Only used by Parser.
419 }; 218 };
420 219
421 220
422 class PreParserIdentifier {
423 public:
424 static PreParserIdentifier Default() {
425 return PreParserIdentifier(kUnknownIdentifier);
426 }
427 static PreParserIdentifier Eval() {
428 return PreParserIdentifier(kEvalIdentifier);
429 }
430 static PreParserIdentifier Arguments() {
431 return PreParserIdentifier(kArgumentsIdentifier);
432 }
433 static PreParserIdentifier FutureReserved() {
434 return PreParserIdentifier(kFutureReservedIdentifier);
435 }
436 static PreParserIdentifier FutureStrictReserved() {
437 return PreParserIdentifier(kFutureStrictReservedIdentifier);
438 }
439 static PreParserIdentifier Yield() {
440 return PreParserIdentifier(kYieldIdentifier);
441 }
442 bool IsEval() { return type_ == kEvalIdentifier; }
443 bool IsArguments() { return type_ == kArgumentsIdentifier; }
444 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
445 bool IsYield() { return type_ == kYieldIdentifier; }
446 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
447 bool IsFutureStrictReserved() {
448 return type_ == kFutureStrictReservedIdentifier;
449 }
450 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
451
452 private:
453 enum Type {
454 kUnknownIdentifier,
455 kFutureReservedIdentifier,
456 kFutureStrictReservedIdentifier,
457 kYieldIdentifier,
458 kEvalIdentifier,
459 kArgumentsIdentifier
460 };
461 explicit PreParserIdentifier(Type type) : type_(type) {}
462 Type type_;
463
464 friend class PreParserExpression;
465 };
466
467
468 // Bits 0 and 1 are used to identify the type of expression:
469 // If bit 0 is set, it's an identifier.
470 // if bit 1 is set, it's a string literal.
471 // If neither is set, it's no particular type, and both set isn't
472 // use yet.
473 class PreParserExpression {
474 public:
475 static PreParserExpression Default() {
476 return PreParserExpression(kUnknownExpression);
477 }
478
479 static PreParserExpression FromIdentifier(PreParserIdentifier id) {
480 return PreParserExpression(kIdentifierFlag |
481 (id.type_ << kIdentifierShift));
482 }
483
484 static PreParserExpression StringLiteral() {
485 return PreParserExpression(kUnknownStringLiteral);
486 }
487
488 static PreParserExpression UseStrictStringLiteral() {
489 return PreParserExpression(kUseStrictString);
490 }
491
492 static PreParserExpression This() {
493 return PreParserExpression(kThisExpression);
494 }
495
496 static PreParserExpression ThisProperty() {
497 return PreParserExpression(kThisPropertyExpression);
498 }
499
500 static PreParserExpression StrictFunction() {
501 return PreParserExpression(kStrictFunctionExpression);
502 }
503
504 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
505
506 // Only works corretly if it is actually an identifier expression.
507 PreParserIdentifier AsIdentifier() {
508 return PreParserIdentifier(
509 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
510 }
511
512 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
513
514 bool IsUseStrictLiteral() {
515 return (code_ & kStringLiteralMask) == kUseStrictString;
516 }
517
518 bool IsThis() { return code_ == kThisExpression; }
519
520 bool IsThisProperty() { return code_ == kThisPropertyExpression; }
521
522 bool IsStrictFunction() { return code_ == kStrictFunctionExpression; }
523
524 private:
525 // First two/three bits are used as flags.
526 // Bit 0 and 1 represent identifiers or strings literals, and are
527 // mutually exclusive, but can both be absent.
528 enum {
529 kUnknownExpression = 0,
530 // Identifiers
531 kIdentifierFlag = 1, // Used to detect labels.
532 kIdentifierShift = 3,
533
534 kStringLiteralFlag = 2, // Used to detect directive prologue.
535 kUnknownStringLiteral = kStringLiteralFlag,
536 kUseStrictString = kStringLiteralFlag | 8,
537 kStringLiteralMask = kUseStrictString,
538
539 // Below here applies if neither identifier nor string literal.
540 kThisExpression = 4,
541 kThisPropertyExpression = 8,
542 kStrictFunctionExpression = 12
543 };
544
545 explicit PreParserExpression(int expression_code) : code_(expression_code) {}
546
547 int code_;
548 };
549
550
551 // PreParserExpressionList doesn't actually store the expressions because
552 // PreParser doesn't need to.
553 class PreParserExpressionList {
554 public:
555 // These functions make list->Add(some_expression) work (and do nothing).
556 PreParserExpressionList* operator->() { return this; }
557 void Add(PreParserExpression, void*) { }
558 };
559
560
561 class PreParserScope {
562 public:
563 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type)
564 : scope_type_(scope_type) {
565 if (outer_scope) {
566 scope_inside_with_ =
567 outer_scope->scope_inside_with_ || is_with_scope();
568 language_mode_ = outer_scope->language_mode();
569 } else {
570 scope_inside_with_ = is_with_scope();
571 language_mode_ = CLASSIC_MODE;
572 }
573 }
574
575 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; }
576 bool is_classic_mode() const {
577 return language_mode() == CLASSIC_MODE;
578 }
579 bool is_extended_mode() {
580 return language_mode() == EXTENDED_MODE;
581 }
582 bool inside_with() const {
583 return scope_inside_with_;
584 }
585
586 ScopeType type() { return scope_type_; }
587 LanguageMode language_mode() const { return language_mode_; }
588 void SetLanguageMode(LanguageMode language_mode) {
589 language_mode_ = language_mode;
590 }
591
592 private:
593 ScopeType scope_type_;
594 bool scope_inside_with_;
595 LanguageMode language_mode_;
596 };
597
598
599 class PreParserFactory {
600 public:
601 explicit PreParserFactory(void* extra_param) {}
602
603 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
604 PreParserIdentifier js_flags,
605 int literal_index,
606 int pos) {
607 return PreParserExpression::Default();
608 }
609 PreParserExpression NewBinaryOperation(Token::Value op,
610 PreParserExpression left,
611 PreParserExpression right, int pos) {
612 return PreParserExpression::Default();
613 }
614 PreParserExpression NewArrayLiteral(PreParserExpressionList values,
615 int literal_index,
616 int pos) {
617 return PreParserExpression::Default();
618 }
619 };
620
621
622 class PreParser;
623
624 class PreParserTraits {
625 public:
626 struct Type {
627 typedef PreParser* Parser;
628
629 // Types used by FunctionState and BlockState.
630 typedef PreParserScope Scope;
631 typedef PreParserFactory Factory;
632 // PreParser doesn't need to store generator variables.
633 typedef void GeneratorVariable;
634 // No interaction with Zones.
635 typedef void Zone;
636
637 // Return types for traversing functions.
638 typedef PreParserIdentifier Identifier;
639 typedef PreParserExpression Expression;
640 typedef PreParserExpressionList ExpressionList;
641 };
642
643 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
644
645 // Custom operations executed when FunctionStates are created and
646 // destructed. (The PreParser doesn't need to do anything.)
647 template<typename FS>
648 static void SetUpFunctionState(FS* function_state, void*) {}
649 template<typename FS>
650 static void TearDownFunctionState(FS* function_state) {}
651
652 // Helper functions for recursive descent.
653 static bool IsEvalOrArguments(PreParserIdentifier identifier) {
654 return identifier.IsEvalOrArguments();
655 }
656
657 // Reporting errors.
658 void ReportMessageAt(Scanner::Location location,
659 const char* message,
660 Vector<const char*> args);
661 void ReportMessageAt(Scanner::Location location,
662 const char* type,
663 const char* name_opt);
664 void ReportMessageAt(int start_pos,
665 int end_pos,
666 const char* type,
667 const char* name_opt);
668
669 // "null" return type creators.
670 static PreParserIdentifier EmptyIdentifier() {
671 return PreParserIdentifier::Default();
672 }
673 static PreParserExpression EmptyExpression() {
674 return PreParserExpression::Default();
675 }
676
677 // Odd-ball literal creators.
678 static PreParserExpression GetLiteralTheHole(int position,
679 PreParserFactory* factory) {
680 return PreParserExpression::Default();
681 }
682
683 // Producing data during the recursive descent.
684 PreParserIdentifier GetSymbol(Scanner* scanner);
685 static PreParserIdentifier NextLiteralString(Scanner* scanner,
686 PretenureFlag tenured) {
687 return PreParserIdentifier::Default();
688 }
689
690 static PreParserExpression ThisExpression(PreParserScope* scope,
691 PreParserFactory* factory) {
692 return PreParserExpression::This();
693 }
694
695 static PreParserExpression ExpressionFromLiteral(
696 Token::Value token, int pos, Scanner* scanner,
697 PreParserFactory* factory) {
698 return PreParserExpression::Default();
699 }
700
701 static PreParserExpression ExpressionFromIdentifier(
702 PreParserIdentifier name, int pos, PreParserScope* scope,
703 PreParserFactory* factory) {
704 return PreParserExpression::FromIdentifier(name);
705 }
706
707 PreParserExpression ExpressionFromString(int pos,
708 Scanner* scanner,
709 PreParserFactory* factory = NULL);
710
711 static PreParserExpressionList NewExpressionList(int size, void* zone) {
712 return PreParserExpressionList();
713 }
714
715 // Temporary glue; these functions will move to ParserBase.
716 PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok);
717 PreParserExpression ParseObjectLiteral(bool* ok);
718 PreParserExpression ParseV8Intrinsic(bool* ok);
719
720 private:
721 PreParser* pre_parser_;
722 };
723
724
725 // Preparsing checks a JavaScript program and emits preparse-data that helps 221 // Preparsing checks a JavaScript program and emits preparse-data that helps
726 // a later parsing to be faster. 222 // a later parsing to be faster.
727 // See preparse-data-format.h for the data format. 223 // See preparse-data-format.h for the data format.
728 224
729 // The PreParser checks that the syntax follows the grammar for JavaScript, 225 // The PreParser checks that the syntax follows the grammar for JavaScript,
730 // and collects some information about the program along the way. 226 // and collects some information about the program along the way.
731 // The grammar check is only performed in order to understand the program 227 // The grammar check is only performed in order to understand the program
732 // sufficiently to deduce some information about it, that can be used 228 // sufficiently to deduce some information about it, that can be used
733 // to speed up later parsing. Finding errors is not the goal of pre-parsing, 229 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
734 // rather it is to speed up properly written and correct programs. 230 // rather it is to speed up properly written and correct programs.
735 // That means that contextual checks (like a label being declared where 231 // That means that contextual checks (like a label being declared where
736 // it is used) are generally omitted. 232 // it is used) are generally omitted.
737 class PreParser : public ParserBase<PreParserTraits> { 233 class PreParser : public ParserBase {
738 public: 234 public:
739 typedef PreParserIdentifier Identifier;
740 typedef PreParserExpression Expression;
741
742 enum PreParseResult { 235 enum PreParseResult {
743 kPreParseStackOverflow, 236 kPreParseStackOverflow,
744 kPreParseSuccess 237 kPreParseSuccess
745 }; 238 };
746 239
747 PreParser(Scanner* scanner, 240 PreParser(Scanner* scanner,
748 ParserRecorder* log, 241 ParserRecorder* log,
749 uintptr_t stack_limit) 242 uintptr_t stack_limit)
750 : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, NULL, this), 243 : ParserBase(scanner, stack_limit),
751 log_(log) {} 244 log_(log),
245 scope_(NULL),
246 parenthesized_function_(false) { }
247
248 ~PreParser() {}
752 249
753 // Pre-parse the program from the character stream; returns true on 250 // Pre-parse the program from the character stream; returns true on
754 // success (even if parsing failed, the pre-parse data successfully 251 // success (even if parsing failed, the pre-parse data successfully
755 // captured the syntax error), and false if a stack-overflow happened 252 // captured the syntax error), and false if a stack-overflow happened
756 // during parsing. 253 // during parsing.
757 PreParseResult PreParseProgram() { 254 PreParseResult PreParseProgram() {
758 PreParserScope scope(scope_, GLOBAL_SCOPE); 255 Scope top_scope(&scope_, kTopLevelScope);
759 FunctionState top_scope(&function_state_, &scope_, &scope, NULL);
760 bool ok = true; 256 bool ok = true;
761 int start_position = scanner()->peek_location().beg_pos; 257 int start_position = scanner()->peek_location().beg_pos;
762 ParseSourceElements(Token::EOS, &ok); 258 ParseSourceElements(Token::EOS, &ok);
763 if (stack_overflow()) return kPreParseStackOverflow; 259 if (stack_overflow()) return kPreParseStackOverflow;
764 if (!ok) { 260 if (!ok) {
765 ReportUnexpectedToken(scanner()->current_token()); 261 ReportUnexpectedToken(scanner()->current_token());
766 } else if (!scope_->is_classic_mode()) { 262 } else if (!scope_->is_classic_mode()) {
767 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); 263 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
768 } 264 }
769 return kPreParseSuccess; 265 return kPreParseSuccess;
770 } 266 }
771 267
772 // Parses a single function literal, from the opening parentheses before 268 // Parses a single function literal, from the opening parentheses before
773 // parameters to the closing brace after the body. 269 // parameters to the closing brace after the body.
774 // Returns a FunctionEntry describing the body of the function in enough 270 // Returns a FunctionEntry describing the body of the function in enough
775 // detail that it can be lazily compiled. 271 // detail that it can be lazily compiled.
776 // The scanner is expected to have matched the "function" or "function*" 272 // The scanner is expected to have matched the "function" or "function*"
777 // keyword and parameters, and have consumed the initial '{'. 273 // keyword and parameters, and have consumed the initial '{'.
778 // At return, unless an error occurred, the scanner is positioned before the 274 // At return, unless an error occurred, the scanner is positioned before the
779 // the final '}'. 275 // the final '}'.
780 PreParseResult PreParseLazyFunction(LanguageMode mode, 276 PreParseResult PreParseLazyFunction(LanguageMode mode,
781 bool is_generator, 277 bool is_generator,
782 ParserRecorder* log); 278 ParserRecorder* log);
783 279
784 private: 280 private:
785 friend class PreParserTraits;
786
787 // These types form an algebra over syntactic categories that is just 281 // These types form an algebra over syntactic categories that is just
788 // rich enough to let us recognize and propagate the constructs that 282 // rich enough to let us recognize and propagate the constructs that
789 // are either being counted in the preparser data, or is important 283 // are either being counted in the preparser data, or is important
790 // to throw the correct syntax error exceptions. 284 // to throw the correct syntax error exceptions.
791 285
286 enum ScopeType {
287 kTopLevelScope,
288 kFunctionScope
289 };
290
792 enum VariableDeclarationContext { 291 enum VariableDeclarationContext {
793 kSourceElement, 292 kSourceElement,
794 kStatement, 293 kStatement,
795 kForStatement 294 kForStatement
796 }; 295 };
797 296
798 // If a list of variable declarations includes any initializers. 297 // If a list of variable declarations includes any initializers.
799 enum VariableDeclarationProperties { 298 enum VariableDeclarationProperties {
800 kHasInitializers, 299 kHasInitializers,
801 kHasNoInitializers 300 kHasNoInitializers
802 }; 301 };
803 302
303 class Expression;
304
305 class Identifier {
306 public:
307 static Identifier Default() {
308 return Identifier(kUnknownIdentifier);
309 }
310 static Identifier Eval() {
311 return Identifier(kEvalIdentifier);
312 }
313 static Identifier Arguments() {
314 return Identifier(kArgumentsIdentifier);
315 }
316 static Identifier FutureReserved() {
317 return Identifier(kFutureReservedIdentifier);
318 }
319 static Identifier FutureStrictReserved() {
320 return Identifier(kFutureStrictReservedIdentifier);
321 }
322 static Identifier Yield() {
323 return Identifier(kYieldIdentifier);
324 }
325 bool IsEval() { return type_ == kEvalIdentifier; }
326 bool IsArguments() { return type_ == kArgumentsIdentifier; }
327 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
328 bool IsYield() { return type_ == kYieldIdentifier; }
329 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
330 bool IsFutureStrictReserved() {
331 return type_ == kFutureStrictReservedIdentifier;
332 }
333 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
334
335 private:
336 enum Type {
337 kUnknownIdentifier,
338 kFutureReservedIdentifier,
339 kFutureStrictReservedIdentifier,
340 kYieldIdentifier,
341 kEvalIdentifier,
342 kArgumentsIdentifier
343 };
344 explicit Identifier(Type type) : type_(type) { }
345 Type type_;
346
347 friend class Expression;
348 };
349
350 // Bits 0 and 1 are used to identify the type of expression:
351 // If bit 0 is set, it's an identifier.
352 // if bit 1 is set, it's a string literal.
353 // If neither is set, it's no particular type, and both set isn't
354 // use yet.
355 class Expression {
356 public:
357 static Expression Default() {
358 return Expression(kUnknownExpression);
359 }
360
361 static Expression FromIdentifier(Identifier id) {
362 return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift));
363 }
364
365 static Expression StringLiteral() {
366 return Expression(kUnknownStringLiteral);
367 }
368
369 static Expression UseStrictStringLiteral() {
370 return Expression(kUseStrictString);
371 }
372
373 static Expression This() {
374 return Expression(kThisExpression);
375 }
376
377 static Expression ThisProperty() {
378 return Expression(kThisPropertyExpression);
379 }
380
381 static Expression StrictFunction() {
382 return Expression(kStrictFunctionExpression);
383 }
384
385 bool IsIdentifier() {
386 return (code_ & kIdentifierFlag) != 0;
387 }
388
389 // Only works corretly if it is actually an identifier expression.
390 PreParser::Identifier AsIdentifier() {
391 return PreParser::Identifier(
392 static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift));
393 }
394
395 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
396
397 bool IsUseStrictLiteral() {
398 return (code_ & kStringLiteralMask) == kUseStrictString;
399 }
400
401 bool IsThis() {
402 return code_ == kThisExpression;
403 }
404
405 bool IsThisProperty() {
406 return code_ == kThisPropertyExpression;
407 }
408
409 bool IsStrictFunction() {
410 return code_ == kStrictFunctionExpression;
411 }
412
413 private:
414 // First two/three bits are used as flags.
415 // Bit 0 and 1 represent identifiers or strings literals, and are
416 // mutually exclusive, but can both be absent.
417 enum {
418 kUnknownExpression = 0,
419 // Identifiers
420 kIdentifierFlag = 1, // Used to detect labels.
421 kIdentifierShift = 3,
422
423 kStringLiteralFlag = 2, // Used to detect directive prologue.
424 kUnknownStringLiteral = kStringLiteralFlag,
425 kUseStrictString = kStringLiteralFlag | 8,
426 kStringLiteralMask = kUseStrictString,
427
428 // Below here applies if neither identifier nor string literal.
429 kThisExpression = 4,
430 kThisPropertyExpression = 8,
431 kStrictFunctionExpression = 12
432 };
433
434 explicit Expression(int expression_code) : code_(expression_code) { }
435
436 int code_;
437 };
438
804 class Statement { 439 class Statement {
805 public: 440 public:
806 static Statement Default() { 441 static Statement Default() {
807 return Statement(kUnknownStatement); 442 return Statement(kUnknownStatement);
808 } 443 }
809 444
810 static Statement FunctionDeclaration() { 445 static Statement FunctionDeclaration() {
811 return Statement(kFunctionDeclaration); 446 return Statement(kFunctionDeclaration);
812 } 447 }
813 448
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 explicit Statement(Type code) : code_(code) {} 482 explicit Statement(Type code) : code_(code) {}
848 Type code_; 483 Type code_;
849 }; 484 };
850 485
851 enum SourceElements { 486 enum SourceElements {
852 kUnknownSourceElements 487 kUnknownSourceElements
853 }; 488 };
854 489
855 typedef int Arguments; 490 typedef int Arguments;
856 491
492 class Scope {
493 public:
494 Scope(Scope** variable, ScopeType type)
495 : variable_(variable),
496 prev_(*variable),
497 type_(type),
498 materialized_literal_count_(0),
499 expected_properties_(0),
500 with_nesting_count_(0),
501 language_mode_(
502 (prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE),
503 is_generator_(false) {
504 *variable = this;
505 }
506 ~Scope() { *variable_ = prev_; }
507 void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
508 void AddProperty() { expected_properties_++; }
509 ScopeType type() { return type_; }
510 int expected_properties() { return expected_properties_; }
511 int materialized_literal_count() { return materialized_literal_count_; }
512 bool IsInsideWith() { return with_nesting_count_ != 0; }
513 bool is_generator() { return is_generator_; }
514 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
515 bool is_classic_mode() {
516 return language_mode_ == CLASSIC_MODE;
517 }
518 LanguageMode language_mode() {
519 return language_mode_;
520 }
521 void set_language_mode(LanguageMode language_mode) {
522 language_mode_ = language_mode;
523 }
524
525 class InsideWith {
526 public:
527 explicit InsideWith(Scope* scope) : scope_(scope) {
528 scope->with_nesting_count_++;
529 }
530
531 ~InsideWith() { scope_->with_nesting_count_--; }
532
533 private:
534 Scope* scope_;
535 DISALLOW_COPY_AND_ASSIGN(InsideWith);
536 };
537
538 private:
539 Scope** const variable_;
540 Scope* const prev_;
541 const ScopeType type_;
542 int materialized_literal_count_;
543 int expected_properties_;
544 int with_nesting_count_;
545 LanguageMode language_mode_;
546 bool is_generator_;
547 };
548
549 // Report syntax error
550 void ReportMessageAt(Scanner::Location location,
551 const char* message,
552 Vector<const char*> args) {
553 ReportMessageAt(location.beg_pos,
554 location.end_pos,
555 message,
556 args.length() > 0 ? args[0] : NULL);
557 }
558 void ReportMessageAt(Scanner::Location location,
559 const char* type,
560 const char* name_opt) {
561 log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
562 }
563 void ReportMessageAt(int start_pos,
564 int end_pos,
565 const char* type,
566 const char* name_opt) {
567 log_->LogMessage(start_pos, end_pos, type, name_opt);
568 }
569
857 // All ParseXXX functions take as the last argument an *ok parameter 570 // All ParseXXX functions take as the last argument an *ok parameter
858 // which is set to false if parsing failed; it is unchanged otherwise. 571 // which is set to false if parsing failed; it is unchanged otherwise.
859 // By making the 'exception handling' explicit, we are forced to check 572 // By making the 'exception handling' explicit, we are forced to check
860 // for failure at the call sites. 573 // for failure at the call sites.
861 Statement ParseSourceElement(bool* ok); 574 Statement ParseSourceElement(bool* ok);
862 SourceElements ParseSourceElements(int end_token, bool* ok); 575 SourceElements ParseSourceElements(int end_token, bool* ok);
863 Statement ParseStatement(bool* ok); 576 Statement ParseStatement(bool* ok);
864 Statement ParseFunctionDeclaration(bool* ok); 577 Statement ParseFunctionDeclaration(bool* ok);
865 Statement ParseBlock(bool* ok); 578 Statement ParseBlock(bool* ok);
866 Statement ParseVariableStatement(VariableDeclarationContext var_context, 579 Statement ParseVariableStatement(VariableDeclarationContext var_context,
867 bool* ok); 580 bool* ok);
868 Statement ParseVariableDeclarations(VariableDeclarationContext var_context, 581 Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
869 VariableDeclarationProperties* decl_props, 582 VariableDeclarationProperties* decl_props,
870 int* num_decl, 583 int* num_decl,
871 bool* ok); 584 bool* ok);
872 Statement ParseExpressionOrLabelledStatement(bool* ok); 585 Statement ParseExpressionOrLabelledStatement(bool* ok);
873 Statement ParseIfStatement(bool* ok); 586 Statement ParseIfStatement(bool* ok);
874 Statement ParseContinueStatement(bool* ok); 587 Statement ParseContinueStatement(bool* ok);
875 Statement ParseBreakStatement(bool* ok); 588 Statement ParseBreakStatement(bool* ok);
876 Statement ParseReturnStatement(bool* ok); 589 Statement ParseReturnStatement(bool* ok);
877 Statement ParseWithStatement(bool* ok); 590 Statement ParseWithStatement(bool* ok);
878 Statement ParseSwitchStatement(bool* ok); 591 Statement ParseSwitchStatement(bool* ok);
879 Statement ParseDoWhileStatement(bool* ok); 592 Statement ParseDoWhileStatement(bool* ok);
880 Statement ParseWhileStatement(bool* ok); 593 Statement ParseWhileStatement(bool* ok);
881 Statement ParseForStatement(bool* ok); 594 Statement ParseForStatement(bool* ok);
882 Statement ParseThrowStatement(bool* ok); 595 Statement ParseThrowStatement(bool* ok);
883 Statement ParseTryStatement(bool* ok); 596 Statement ParseTryStatement(bool* ok);
884 Statement ParseDebuggerStatement(bool* ok); 597 Statement ParseDebuggerStatement(bool* ok);
885 598
599 Expression ParseExpression(bool accept_IN, bool* ok);
886 Expression ParseAssignmentExpression(bool accept_IN, bool* ok); 600 Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
887 Expression ParseYieldExpression(bool* ok); 601 Expression ParseYieldExpression(bool* ok);
888 Expression ParseConditionalExpression(bool accept_IN, bool* ok); 602 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
889 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); 603 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
890 Expression ParseUnaryExpression(bool* ok); 604 Expression ParseUnaryExpression(bool* ok);
891 Expression ParsePostfixExpression(bool* ok); 605 Expression ParsePostfixExpression(bool* ok);
892 Expression ParseLeftHandSideExpression(bool* ok); 606 Expression ParseLeftHandSideExpression(bool* ok);
607 Expression ParseNewExpression(bool* ok);
893 Expression ParseMemberExpression(bool* ok); 608 Expression ParseMemberExpression(bool* ok);
894 Expression ParseMemberExpressionContinuation(PreParserExpression expression, 609 Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
895 bool* ok); 610 Expression ParsePrimaryExpression(bool* ok);
896 Expression ParseMemberWithNewPrefixesExpression(bool* ok); 611 Expression ParseArrayLiteral(bool* ok);
897 Expression ParseObjectLiteral(bool* ok); 612 Expression ParseObjectLiteral(bool* ok);
613 Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
898 Expression ParseV8Intrinsic(bool* ok); 614 Expression ParseV8Intrinsic(bool* ok);
899 615
900 Arguments ParseArguments(bool* ok); 616 Arguments ParseArguments(bool* ok);
901 Expression ParseFunctionLiteral( 617 Expression ParseFunctionLiteral(
902 Identifier name, 618 Identifier name,
903 Scanner::Location function_name_location, 619 Scanner::Location function_name_location,
904 bool name_is_strict_reserved, 620 bool name_is_strict_reserved,
905 bool is_generator, 621 bool is_generator,
906 bool* ok); 622 bool* ok);
907 void ParseLazyFunctionLiteralBody(bool* ok); 623 void ParseLazyFunctionLiteralBody(bool* ok);
908 624
625 Identifier ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool* ok);
626 Identifier ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
627 bool* ok);
628 Identifier ParseIdentifierName(bool* ok);
629 Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
630 bool* is_set,
631 bool* ok);
632
909 // Logs the currently parsed literal as a symbol in the preparser data. 633 // Logs the currently parsed literal as a symbol in the preparser data.
910 void LogSymbol(); 634 void LogSymbol();
635 // Log the currently parsed identifier.
636 Identifier GetIdentifierSymbol();
911 // Log the currently parsed string literal. 637 // Log the currently parsed string literal.
912 Expression GetStringSymbol(); 638 Expression GetStringSymbol();
913 639
640 void set_language_mode(LanguageMode language_mode) {
641 scope_->set_language_mode(language_mode);
642 }
643
644 virtual bool is_classic_mode() {
645 return scope_->language_mode() == CLASSIC_MODE;
646 }
647
648 bool is_extended_mode() {
649 return scope_->language_mode() == EXTENDED_MODE;
650 }
651
652 LanguageMode language_mode() { return scope_->language_mode(); }
653
914 bool CheckInOrOf(bool accept_OF); 654 bool CheckInOrOf(bool accept_OF);
915 655
916 ParserRecorder* log_; 656 ParserRecorder* log_;
657 Scope* scope_;
658 bool parenthesized_function_;
917 }; 659 };
918 660
919
920 template<class Traits>
921 ParserBase<Traits>::FunctionState::FunctionState(
922 FunctionState** function_state_stack,
923 typename Traits::Type::Scope** scope_stack,
924 typename Traits::Type::Scope* scope,
925 typename Traits::Type::Zone* extra_param)
926 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
927 next_handler_index_(0),
928 expected_property_count_(0),
929 is_generator_(false),
930 generator_object_variable_(NULL),
931 function_state_stack_(function_state_stack),
932 outer_function_state_(*function_state_stack),
933 scope_stack_(scope_stack),
934 outer_scope_(*scope_stack),
935 isolate_(NULL),
936 saved_ast_node_id_(0),
937 factory_(extra_param) {
938 *scope_stack_ = scope;
939 *function_state_stack = this;
940 Traits::SetUpFunctionState(this, extra_param);
941 }
942
943
944 template<class Traits>
945 ParserBase<Traits>::FunctionState::~FunctionState() {
946 *scope_stack_ = outer_scope_;
947 *function_state_stack_ = outer_function_state_;
948 Traits::TearDownFunctionState(this);
949 }
950
951
952 template<class Traits>
953 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
954 // We don't report stack overflows here, to avoid increasing the
955 // stack depth even further. Instead we report it after parsing is
956 // over, in ParseProgram.
957 if (token == Token::ILLEGAL && stack_overflow()) {
958 return;
959 }
960 Scanner::Location source_location = scanner()->location();
961
962 // Four of the tokens are treated specially
963 switch (token) {
964 case Token::EOS:
965 return ReportMessageAt(source_location, "unexpected_eos");
966 case Token::NUMBER:
967 return ReportMessageAt(source_location, "unexpected_token_number");
968 case Token::STRING:
969 return ReportMessageAt(source_location, "unexpected_token_string");
970 case Token::IDENTIFIER:
971 return ReportMessageAt(source_location, "unexpected_token_identifier");
972 case Token::FUTURE_RESERVED_WORD:
973 return ReportMessageAt(source_location, "unexpected_reserved");
974 case Token::YIELD:
975 case Token::FUTURE_STRICT_RESERVED_WORD:
976 return ReportMessageAt(source_location,
977 is_classic_mode() ? "unexpected_token_identifier"
978 : "unexpected_strict_reserved");
979 default:
980 const char* name = Token::String(token);
981 ASSERT(name != NULL);
982 Traits::ReportMessageAt(
983 source_location, "unexpected_token", Vector<const char*>(&name, 1));
984 }
985 }
986
987
988 template<class Traits>
989 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier(
990 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
991 bool* ok) {
992 Token::Value next = Next();
993 if (next == Token::IDENTIFIER) {
994 typename Traits::Type::Identifier name = this->GetSymbol(scanner());
995 if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
996 !is_classic_mode() && this->IsEvalOrArguments(name)) {
997 ReportMessageAt(scanner()->location(), "strict_eval_arguments");
998 *ok = false;
999 }
1000 return name;
1001 } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1002 (next == Token::YIELD && !is_generator()))) {
1003 return this->GetSymbol(scanner());
1004 } else {
1005 this->ReportUnexpectedToken(next);
1006 *ok = false;
1007 return Traits::EmptyIdentifier();
1008 }
1009 }
1010
1011
1012 template <class Traits>
1013 typename Traits::Type::Identifier ParserBase<
1014 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
1015 bool* ok) {
1016 Token::Value next = Next();
1017 if (next == Token::IDENTIFIER) {
1018 *is_strict_reserved = false;
1019 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1020 (next == Token::YIELD && !this->is_generator())) {
1021 *is_strict_reserved = true;
1022 } else {
1023 ReportUnexpectedToken(next);
1024 *ok = false;
1025 return Traits::EmptyIdentifier();
1026 }
1027 return this->GetSymbol(scanner());
1028 }
1029
1030
1031 template <class Traits>
1032 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName(
1033 bool* ok) {
1034 Token::Value next = Next();
1035 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
1036 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
1037 this->ReportUnexpectedToken(next);
1038 *ok = false;
1039 return Traits::EmptyIdentifier();
1040 }
1041 return this->GetSymbol(scanner());
1042 }
1043
1044
1045 template <class Traits>
1046 typename Traits::Type::Identifier
1047 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
1048 bool* is_set,
1049 bool* ok) {
1050 typename Traits::Type::Identifier result = ParseIdentifierName(ok);
1051 if (!*ok) return Traits::EmptyIdentifier();
1052 if (scanner()->is_literal_ascii() &&
1053 scanner()->literal_length() == 3) {
1054 const char* token = scanner()->literal_ascii_string().start();
1055 *is_get = strncmp(token, "get", 3) == 0;
1056 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1057 }
1058 return result;
1059 }
1060
1061
1062 template <class Traits>
1063 typename Traits::Type::Expression
1064 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
1065 int pos = peek_position();
1066 if (!scanner()->ScanRegExpPattern(seen_equal)) {
1067 Next();
1068 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
1069 *ok = false;
1070 return Traits::EmptyExpression();
1071 }
1072
1073 int literal_index = function_state_->NextMaterializedLiteralIndex();
1074
1075 typename Traits::Type::Identifier js_pattern =
1076 this->NextLiteralString(scanner(), TENURED);
1077 if (!scanner()->ScanRegExpFlags()) {
1078 Next();
1079 ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
1080 *ok = false;
1081 return Traits::EmptyExpression();
1082 }
1083 typename Traits::Type::Identifier js_flags =
1084 this->NextLiteralString(scanner(), TENURED);
1085 Next();
1086 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
1087 }
1088
1089
1090 #define CHECK_OK ok); \
1091 if (!*ok) return this->EmptyExpression(); \
1092 ((void)0
1093 #define DUMMY ) // to make indentation work
1094 #undef DUMMY
1095
1096 template <class Traits>
1097 typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression(
1098 bool* ok) {
1099 // PrimaryExpression ::
1100 // 'this'
1101 // 'null'
1102 // 'true'
1103 // 'false'
1104 // Identifier
1105 // Number
1106 // String
1107 // ArrayLiteral
1108 // ObjectLiteral
1109 // RegExpLiteral
1110 // '(' Expression ')'
1111
1112 int pos = peek_position();
1113 typename Traits::Type::Expression result = this->EmptyExpression();
1114 Token::Value token = peek();
1115 switch (token) {
1116 case Token::THIS: {
1117 Consume(Token::THIS);
1118 result = this->ThisExpression(scope_, factory());
1119 break;
1120 }
1121
1122 case Token::NULL_LITERAL:
1123 case Token::TRUE_LITERAL:
1124 case Token::FALSE_LITERAL:
1125 case Token::NUMBER:
1126 Next();
1127 result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
1128 break;
1129
1130 case Token::IDENTIFIER:
1131 case Token::YIELD:
1132 case Token::FUTURE_STRICT_RESERVED_WORD: {
1133 // Using eval or arguments in this context is OK even in strict mode.
1134 typename Traits::Type::Identifier name =
1135 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1136 result =
1137 this->ExpressionFromIdentifier(name, pos, scope_, factory());
1138 break;
1139 }
1140
1141 case Token::STRING: {
1142 Consume(Token::STRING);
1143 result = this->ExpressionFromString(pos, scanner(), factory());
1144 break;
1145 }
1146
1147 case Token::ASSIGN_DIV:
1148 result = this->ParseRegExpLiteral(true, CHECK_OK);
1149 break;
1150
1151 case Token::DIV:
1152 result = this->ParseRegExpLiteral(false, CHECK_OK);
1153 break;
1154
1155 case Token::LBRACK:
1156 result = this->ParseArrayLiteral(CHECK_OK);
1157 break;
1158
1159 case Token::LBRACE:
1160 result = this->ParseObjectLiteral(CHECK_OK);
1161 break;
1162
1163 case Token::LPAREN:
1164 Consume(Token::LPAREN);
1165 // Heuristically try to detect immediately called functions before
1166 // seeing the call parentheses.
1167 parenthesized_function_ = (peek() == Token::FUNCTION);
1168 result = this->ParseExpression(true, CHECK_OK);
1169 Expect(Token::RPAREN, CHECK_OK);
1170 break;
1171
1172 case Token::MOD:
1173 if (allow_natives_syntax() || extension_ != NULL) {
1174 result = this->ParseV8Intrinsic(CHECK_OK);
1175 break;
1176 }
1177 // If we're not allowing special syntax we fall-through to the
1178 // default case.
1179
1180 default: {
1181 Next();
1182 ReportUnexpectedToken(token);
1183 *ok = false;
1184 }
1185 }
1186
1187 return result;
1188 }
1189
1190 // Precedence = 1
1191 template <class Traits>
1192 typename Traits::Type::Expression ParserBase<Traits>::ParseExpression(
1193 bool accept_IN, bool* ok) {
1194 // Expression ::
1195 // AssignmentExpression
1196 // Expression ',' AssignmentExpression
1197
1198 typename Traits::Type::Expression result =
1199 this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1200 while (peek() == Token::COMMA) {
1201 Expect(Token::COMMA, CHECK_OK);
1202 int pos = position();
1203 typename Traits::Type::Expression right =
1204 this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1205 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
1206 }
1207 return result;
1208 }
1209
1210
1211 template <class Traits>
1212 typename Traits::Type::Expression ParserBase<Traits>::ParseArrayLiteral(
1213 bool* ok) {
1214 // ArrayLiteral ::
1215 // '[' Expression? (',' Expression?)* ']'
1216
1217 int pos = peek_position();
1218 typename Traits::Type::ExpressionList values =
1219 this->NewExpressionList(4, zone_);
1220 Expect(Token::LBRACK, CHECK_OK);
1221 while (peek() != Token::RBRACK) {
1222 typename Traits::Type::Expression elem = this->EmptyExpression();
1223 if (peek() == Token::COMMA) {
1224 elem = this->GetLiteralTheHole(peek_position(), factory());
1225 } else {
1226 elem = this->ParseAssignmentExpression(true, CHECK_OK);
1227 }
1228 values->Add(elem, zone_);
1229 if (peek() != Token::RBRACK) {
1230 Expect(Token::COMMA, CHECK_OK);
1231 }
1232 }
1233 Expect(Token::RBRACK, CHECK_OK);
1234
1235 // Update the scope information before the pre-parsing bailout.
1236 int literal_index = function_state_->NextMaterializedLiteralIndex();
1237
1238 return factory()->NewArrayLiteral(values, literal_index, pos);
1239 }
1240
1241 #undef CHECK_OK
1242
1243
1244 template <typename Traits>
1245 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
1246 Token::Value property,
1247 PropertyKind type,
1248 bool* ok) {
1249 int old;
1250 if (property == Token::NUMBER) {
1251 old = finder_.AddNumber(scanner()->literal_ascii_string(), type);
1252 } else if (scanner()->is_literal_ascii()) {
1253 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type);
1254 } else {
1255 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type);
1256 }
1257 PropertyKind old_type = static_cast<PropertyKind>(old);
1258 if (HasConflict(old_type, type)) {
1259 if (IsDataDataConflict(old_type, type)) {
1260 // Both are data properties.
1261 if (language_mode_ == CLASSIC_MODE) return;
1262 parser()->ReportMessageAt(scanner()->location(),
1263 "strict_duplicate_property");
1264 } else if (IsDataAccessorConflict(old_type, type)) {
1265 // Both a data and an accessor property with the same name.
1266 parser()->ReportMessageAt(scanner()->location(),
1267 "accessor_data_property");
1268 } else {
1269 ASSERT(IsAccessorAccessorConflict(old_type, type));
1270 // Both accessors of the same type.
1271 parser()->ReportMessageAt(scanner()->location(),
1272 "accessor_get_set");
1273 }
1274 *ok = false;
1275 }
1276 }
1277
1278
1279 } } // v8::internal 661 } } // v8::internal
1280 662
1281 #endif // V8_PREPARSER_H 663 #endif // V8_PREPARSER_H
OLDNEW
« no previous file with comments | « src/preparse-data.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698