OLD | NEW |
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 18 matching lines...) Expand all Loading... |
29 #define V8_PREPARSER_H | 29 #define V8_PREPARSER_H |
30 | 30 |
31 #include "hashmap.h" | 31 #include "hashmap.h" |
32 #include "token.h" | 32 #include "token.h" |
33 #include "scanner.h" | 33 #include "scanner.h" |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 // Common base class shared between parser and pre-parser. | 38 // Common base class shared between parser and pre-parser. |
39 template <typename Traits> | 39 class ParserBase { |
40 class ParserBase : public Traits { | |
41 public: | 40 public: |
42 ParserBase(Scanner* scanner, uintptr_t stack_limit, | 41 ParserBase(Scanner* scanner, uintptr_t stack_limit) |
43 typename Traits::ParserType this_object) | 42 : scanner_(scanner), |
44 : Traits(this_object), | |
45 scanner_(scanner), | |
46 stack_limit_(stack_limit), | 43 stack_limit_(stack_limit), |
47 stack_overflow_(false), | 44 stack_overflow_(false), |
48 allow_lazy_(false), | 45 allow_lazy_(false), |
49 allow_natives_syntax_(false), | 46 allow_natives_syntax_(false), |
50 allow_generators_(false), | 47 allow_generators_(false), |
51 allow_for_of_(false) { } | 48 allow_for_of_(false) { } |
| 49 // TODO(mstarzinger): Only virtual until message reporting has been unified. |
| 50 virtual ~ParserBase() { } |
52 | 51 |
53 // Getters that indicate whether certain syntactical constructs are | 52 // Getters that indicate whether certain syntactical constructs are |
54 // allowed to be parsed by this instance of the parser. | 53 // allowed to be parsed by this instance of the parser. |
55 bool allow_lazy() const { return allow_lazy_; } | 54 bool allow_lazy() const { return allow_lazy_; } |
56 bool allow_natives_syntax() const { return allow_natives_syntax_; } | 55 bool allow_natives_syntax() const { return allow_natives_syntax_; } |
57 bool allow_generators() const { return allow_generators_; } | 56 bool allow_generators() const { return allow_generators_; } |
58 bool allow_for_of() const { return allow_for_of_; } | 57 bool allow_for_of() const { return allow_for_of_; } |
59 bool allow_modules() const { return scanner()->HarmonyModules(); } | 58 bool allow_modules() const { return scanner()->HarmonyModules(); } |
60 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } | 59 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } |
61 bool allow_harmony_numeric_literals() const { | 60 bool allow_harmony_numeric_literals() const { |
(...skipping 19 matching lines...) Expand all Loading... |
81 kAllowEvalOrArguments, | 80 kAllowEvalOrArguments, |
82 kDontAllowEvalOrArguments | 81 kDontAllowEvalOrArguments |
83 }; | 82 }; |
84 | 83 |
85 Scanner* scanner() const { return scanner_; } | 84 Scanner* scanner() const { return scanner_; } |
86 int position() { return scanner_->location().beg_pos; } | 85 int position() { return scanner_->location().beg_pos; } |
87 int peek_position() { return scanner_->peek_location().beg_pos; } | 86 int peek_position() { return scanner_->peek_location().beg_pos; } |
88 bool stack_overflow() const { return stack_overflow_; } | 87 bool stack_overflow() const { return stack_overflow_; } |
89 void set_stack_overflow() { stack_overflow_ = true; } | 88 void set_stack_overflow() { stack_overflow_ = true; } |
90 | 89 |
| 90 virtual bool is_classic_mode() = 0; |
| 91 |
91 INLINE(Token::Value peek()) { | 92 INLINE(Token::Value peek()) { |
92 if (stack_overflow_) return Token::ILLEGAL; | 93 if (stack_overflow_) return Token::ILLEGAL; |
93 return scanner()->peek(); | 94 return scanner()->peek(); |
94 } | 95 } |
95 | 96 |
96 INLINE(Token::Value Next()) { | 97 INLINE(Token::Value Next()) { |
97 if (stack_overflow_) return Token::ILLEGAL; | 98 if (stack_overflow_) return Token::ILLEGAL; |
98 { | 99 { |
99 int marker; | 100 int marker; |
100 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) { | 101 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) { |
(...skipping 23 matching lines...) Expand all Loading... |
124 } | 125 } |
125 | 126 |
126 void Expect(Token::Value token, bool* ok) { | 127 void Expect(Token::Value token, bool* ok) { |
127 Token::Value next = Next(); | 128 Token::Value next = Next(); |
128 if (next != token) { | 129 if (next != token) { |
129 ReportUnexpectedToken(next); | 130 ReportUnexpectedToken(next); |
130 *ok = false; | 131 *ok = false; |
131 } | 132 } |
132 } | 133 } |
133 | 134 |
134 void ExpectSemicolon(bool* ok) { | 135 bool peek_any_identifier(); |
135 // Check for automatic semicolon insertion according to | 136 void ExpectSemicolon(bool* ok); |
136 // the rules given in ECMA-262, section 7.9, page 21. | 137 bool CheckContextualKeyword(Vector<const char> keyword); |
137 Token::Value tok = peek(); | 138 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok); |
138 if (tok == Token::SEMICOLON) { | |
139 Next(); | |
140 return; | |
141 } | |
142 if (scanner()->HasAnyLineTerminatorBeforeNext() || | |
143 tok == Token::RBRACE || | |
144 tok == Token::EOS) { | |
145 return; | |
146 } | |
147 Expect(Token::SEMICOLON, ok); | |
148 } | |
149 | 139 |
150 bool peek_any_identifier() { | 140 // Strict mode octal literal validation. |
151 Token::Value next = peek(); | 141 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok); |
152 return next == Token::IDENTIFIER || | |
153 next == Token::FUTURE_RESERVED_WORD || | |
154 next == Token::FUTURE_STRICT_RESERVED_WORD || | |
155 next == Token::YIELD; | |
156 } | |
157 | |
158 bool CheckContextualKeyword(Vector<const char> keyword) { | |
159 if (peek() == Token::IDENTIFIER && | |
160 scanner()->is_next_contextual_keyword(keyword)) { | |
161 Consume(Token::IDENTIFIER); | |
162 return true; | |
163 } | |
164 return false; | |
165 } | |
166 | |
167 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { | |
168 Expect(Token::IDENTIFIER, ok); | |
169 if (!*ok) return; | |
170 if (!scanner()->is_literal_contextual_keyword(keyword)) { | |
171 ReportUnexpectedToken(scanner()->current_token()); | |
172 *ok = false; | |
173 } | |
174 } | |
175 | |
176 // Checks whether an octal literal was last seen between beg_pos and end_pos. | |
177 // If so, reports an error. Only called for strict mode. | |
178 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { | |
179 Scanner::Location octal = scanner()->octal_position(); | |
180 if (octal.IsValid() && beg_pos <= octal.beg_pos && | |
181 octal.end_pos <= end_pos) { | |
182 ReportMessageAt(octal, "strict_octal_literal"); | |
183 scanner()->clear_octal_position(); | |
184 *ok = false; | |
185 } | |
186 } | |
187 | 142 |
188 // Determine precedence of given token. | 143 // Determine precedence of given token. |
189 static int Precedence(Token::Value token, bool accept_IN) { | 144 static int Precedence(Token::Value token, bool accept_IN); |
190 if (token == Token::IN && !accept_IN) | |
191 return 0; // 0 precedence will terminate binary expression parsing | |
192 return Token::Precedence(token); | |
193 } | |
194 | 145 |
195 // Report syntax errors. | 146 // Report syntax errors. |
196 void ReportMessage(const char* message, Vector<const char*> args) { | 147 void ReportUnexpectedToken(Token::Value token); |
197 Scanner::Location source_location = scanner()->location(); | 148 void ReportMessageAt(Scanner::Location location, const char* type) { |
198 Traits::ReportMessageAt(source_location, message, args); | 149 ReportMessageAt(location, type, Vector<const char*>::empty()); |
199 } | 150 } |
200 | 151 virtual void ReportMessageAt(Scanner::Location source_location, |
201 void ReportMessageAt(Scanner::Location location, const char* message) { | 152 const char* message, |
202 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); | 153 Vector<const char*> args) = 0; |
203 } | |
204 | |
205 void ReportUnexpectedToken(Token::Value token); | |
206 | |
207 // Recursive descent functions: | |
208 | |
209 // Parses an identifier that is valid for the current scope, in particular it | |
210 // fails on strict mode future reserved keywords in a strict scope. If | |
211 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | |
212 // "arguments" as identifier even in strict mode (this is needed in cases like | |
213 // "var foo = eval;"). | |
214 typename Traits::IdentifierType ParseIdentifier( | |
215 AllowEvalOrArgumentsAsIdentifier, | |
216 bool* ok); | |
217 // Parses an identifier or a strict mode future reserved word, and indicate | |
218 // whether it is strict mode future reserved. | |
219 typename Traits::IdentifierType ParseIdentifierOrStrictReservedWord( | |
220 bool* is_strict_reserved, | |
221 bool* ok); | |
222 typename Traits::IdentifierType ParseIdentifierName(bool* ok); | |
223 // Parses an identifier and determines whether or not it is 'get' or 'set'. | |
224 typename Traits::IdentifierType ParseIdentifierNameOrGetOrSet(bool* is_get, | |
225 bool* is_set, | |
226 bool* ok); | |
227 | 154 |
228 // Used to detect duplicates in object literals. Each of the values | 155 // Used to detect duplicates in object literals. Each of the values |
229 // kGetterProperty, kSetterProperty and kValueProperty represents | 156 // kGetterProperty, kSetterProperty and kValueProperty represents |
230 // a type of object literal property. When parsing a property, its | 157 // a type of object literal property. When parsing a property, its |
231 // type value is stored in the DuplicateFinder for the property name. | 158 // type value is stored in the DuplicateFinder for the property name. |
232 // 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 |
233 // an incompatibility. | 160 // an incompatibility. |
234 // 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 |
235 // kGetterProperty and kSetterProperty doesn't intersect, but not if it | 162 // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
236 // 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 uintptr_t stack_limit_; | 211 uintptr_t stack_limit_; |
285 bool stack_overflow_; | 212 bool stack_overflow_; |
286 | 213 |
287 bool allow_lazy_; | 214 bool allow_lazy_; |
288 bool allow_natives_syntax_; | 215 bool allow_natives_syntax_; |
289 bool allow_generators_; | 216 bool allow_generators_; |
290 bool allow_for_of_; | 217 bool allow_for_of_; |
291 }; | 218 }; |
292 | 219 |
293 | 220 |
294 class PreParserIdentifier { | |
295 public: | |
296 static PreParserIdentifier Default() { | |
297 return PreParserIdentifier(kUnknownIdentifier); | |
298 } | |
299 static PreParserIdentifier Eval() { | |
300 return PreParserIdentifier(kEvalIdentifier); | |
301 } | |
302 static PreParserIdentifier Arguments() { | |
303 return PreParserIdentifier(kArgumentsIdentifier); | |
304 } | |
305 static PreParserIdentifier FutureReserved() { | |
306 return PreParserIdentifier(kFutureReservedIdentifier); | |
307 } | |
308 static PreParserIdentifier FutureStrictReserved() { | |
309 return PreParserIdentifier(kFutureStrictReservedIdentifier); | |
310 } | |
311 static PreParserIdentifier Yield() { | |
312 return PreParserIdentifier(kYieldIdentifier); | |
313 } | |
314 bool IsEval() { return type_ == kEvalIdentifier; } | |
315 bool IsArguments() { return type_ == kArgumentsIdentifier; } | |
316 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; } | |
317 bool IsYield() { return type_ == kYieldIdentifier; } | |
318 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; } | |
319 bool IsFutureStrictReserved() { | |
320 return type_ == kFutureStrictReservedIdentifier; | |
321 } | |
322 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; } | |
323 | |
324 private: | |
325 enum Type { | |
326 kUnknownIdentifier, | |
327 kFutureReservedIdentifier, | |
328 kFutureStrictReservedIdentifier, | |
329 kYieldIdentifier, | |
330 kEvalIdentifier, | |
331 kArgumentsIdentifier | |
332 }; | |
333 explicit PreParserIdentifier(Type type) : type_(type) {} | |
334 Type type_; | |
335 | |
336 friend class PreParserExpression; | |
337 }; | |
338 | |
339 | |
340 // Bits 0 and 1 are used to identify the type of expression: | |
341 // If bit 0 is set, it's an identifier. | |
342 // if bit 1 is set, it's a string literal. | |
343 // If neither is set, it's no particular type, and both set isn't | |
344 // use yet. | |
345 class PreParserExpression { | |
346 public: | |
347 static PreParserExpression Default() { | |
348 return PreParserExpression(kUnknownExpression); | |
349 } | |
350 | |
351 static PreParserExpression FromIdentifier(PreParserIdentifier id) { | |
352 return PreParserExpression(kIdentifierFlag | | |
353 (id.type_ << kIdentifierShift)); | |
354 } | |
355 | |
356 static PreParserExpression StringLiteral() { | |
357 return PreParserExpression(kUnknownStringLiteral); | |
358 } | |
359 | |
360 static PreParserExpression UseStrictStringLiteral() { | |
361 return PreParserExpression(kUseStrictString); | |
362 } | |
363 | |
364 static PreParserExpression This() { | |
365 return PreParserExpression(kThisExpression); | |
366 } | |
367 | |
368 static PreParserExpression ThisProperty() { | |
369 return PreParserExpression(kThisPropertyExpression); | |
370 } | |
371 | |
372 static PreParserExpression StrictFunction() { | |
373 return PreParserExpression(kStrictFunctionExpression); | |
374 } | |
375 | |
376 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; } | |
377 | |
378 // Only works corretly if it is actually an identifier expression. | |
379 PreParserIdentifier AsIdentifier() { | |
380 return PreParserIdentifier( | |
381 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); | |
382 } | |
383 | |
384 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } | |
385 | |
386 bool IsUseStrictLiteral() { | |
387 return (code_ & kStringLiteralMask) == kUseStrictString; | |
388 } | |
389 | |
390 bool IsThis() { return code_ == kThisExpression; } | |
391 | |
392 bool IsThisProperty() { return code_ == kThisPropertyExpression; } | |
393 | |
394 bool IsStrictFunction() { return code_ == kStrictFunctionExpression; } | |
395 | |
396 private: | |
397 // First two/three bits are used as flags. | |
398 // Bit 0 and 1 represent identifiers or strings literals, and are | |
399 // mutually exclusive, but can both be absent. | |
400 enum { | |
401 kUnknownExpression = 0, | |
402 // Identifiers | |
403 kIdentifierFlag = 1, // Used to detect labels. | |
404 kIdentifierShift = 3, | |
405 | |
406 kStringLiteralFlag = 2, // Used to detect directive prologue. | |
407 kUnknownStringLiteral = kStringLiteralFlag, | |
408 kUseStrictString = kStringLiteralFlag | 8, | |
409 kStringLiteralMask = kUseStrictString, | |
410 | |
411 // Below here applies if neither identifier nor string literal. | |
412 kThisExpression = 4, | |
413 kThisPropertyExpression = 8, | |
414 kStrictFunctionExpression = 12 | |
415 }; | |
416 | |
417 explicit PreParserExpression(int expression_code) : code_(expression_code) {} | |
418 | |
419 int code_; | |
420 }; | |
421 | |
422 class PreParser; | |
423 | |
424 | |
425 class PreParserTraits { | |
426 public: | |
427 typedef PreParser* ParserType; | |
428 // Return types for traversing functions. | |
429 typedef PreParserIdentifier IdentifierType; | |
430 | |
431 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} | |
432 | |
433 // Helper functions for recursive descent. | |
434 bool is_classic_mode() const; | |
435 bool is_generator() const; | |
436 static bool IsEvalOrArguments(IdentifierType identifier) { | |
437 return identifier.IsEvalOrArguments(); | |
438 } | |
439 | |
440 // Reporting errors. | |
441 void ReportMessageAt(Scanner::Location location, | |
442 const char* message, | |
443 Vector<const char*> args); | |
444 void ReportMessageAt(Scanner::Location location, | |
445 const char* type, | |
446 const char* name_opt); | |
447 void ReportMessageAt(int start_pos, | |
448 int end_pos, | |
449 const char* type, | |
450 const char* name_opt); | |
451 | |
452 // Identifiers: | |
453 static IdentifierType EmptyIdentifier() { | |
454 return PreParserIdentifier::Default(); | |
455 } | |
456 | |
457 IdentifierType GetSymbol(); | |
458 | |
459 private: | |
460 PreParser* pre_parser_; | |
461 }; | |
462 | |
463 | |
464 // Preparsing checks a JavaScript program and emits preparse-data that helps | 221 // Preparsing checks a JavaScript program and emits preparse-data that helps |
465 // a later parsing to be faster. | 222 // a later parsing to be faster. |
466 // See preparse-data-format.h for the data format. | 223 // See preparse-data-format.h for the data format. |
467 | 224 |
468 // The PreParser checks that the syntax follows the grammar for JavaScript, | 225 // The PreParser checks that the syntax follows the grammar for JavaScript, |
469 // and collects some information about the program along the way. | 226 // and collects some information about the program along the way. |
470 // 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 |
471 // sufficiently to deduce some information about it, that can be used | 228 // sufficiently to deduce some information about it, that can be used |
472 // 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, |
473 // rather it is to speed up properly written and correct programs. | 230 // rather it is to speed up properly written and correct programs. |
474 // That means that contextual checks (like a label being declared where | 231 // That means that contextual checks (like a label being declared where |
475 // it is used) are generally omitted. | 232 // it is used) are generally omitted. |
476 class PreParser : public ParserBase<PreParserTraits> { | 233 class PreParser : public ParserBase { |
477 public: | 234 public: |
478 typedef PreParserIdentifier Identifier; | |
479 typedef PreParserExpression Expression; | |
480 | |
481 enum PreParseResult { | 235 enum PreParseResult { |
482 kPreParseStackOverflow, | 236 kPreParseStackOverflow, |
483 kPreParseSuccess | 237 kPreParseSuccess |
484 }; | 238 }; |
485 | 239 |
486 PreParser(Scanner* scanner, | 240 PreParser(Scanner* scanner, |
487 ParserRecorder* log, | 241 ParserRecorder* log, |
488 uintptr_t stack_limit) | 242 uintptr_t stack_limit) |
489 : ParserBase(scanner, stack_limit, this), | 243 : ParserBase(scanner, stack_limit), |
490 log_(log), | 244 log_(log), |
491 scope_(NULL), | 245 scope_(NULL), |
492 parenthesized_function_(false) { } | 246 parenthesized_function_(false) { } |
493 | 247 |
494 ~PreParser() {} | 248 ~PreParser() {} |
495 | 249 |
496 // Pre-parse the program from the character stream; returns true on | 250 // Pre-parse the program from the character stream; returns true on |
497 // success (even if parsing failed, the pre-parse data successfully | 251 // success (even if parsing failed, the pre-parse data successfully |
498 // captured the syntax error), and false if a stack-overflow happened | 252 // captured the syntax error), and false if a stack-overflow happened |
499 // during parsing. | 253 // during parsing. |
(...skipping 17 matching lines...) Expand all Loading... |
517 // detail that it can be lazily compiled. | 271 // detail that it can be lazily compiled. |
518 // The scanner is expected to have matched the "function" or "function*" | 272 // The scanner is expected to have matched the "function" or "function*" |
519 // keyword and parameters, and have consumed the initial '{'. | 273 // keyword and parameters, and have consumed the initial '{'. |
520 // 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 |
521 // the final '}'. | 275 // the final '}'. |
522 PreParseResult PreParseLazyFunction(LanguageMode mode, | 276 PreParseResult PreParseLazyFunction(LanguageMode mode, |
523 bool is_generator, | 277 bool is_generator, |
524 ParserRecorder* log); | 278 ParserRecorder* log); |
525 | 279 |
526 private: | 280 private: |
527 friend class PreParserTraits; | |
528 | |
529 // These types form an algebra over syntactic categories that is just | 281 // These types form an algebra over syntactic categories that is just |
530 // rich enough to let us recognize and propagate the constructs that | 282 // rich enough to let us recognize and propagate the constructs that |
531 // are either being counted in the preparser data, or is important | 283 // are either being counted in the preparser data, or is important |
532 // to throw the correct syntax error exceptions. | 284 // to throw the correct syntax error exceptions. |
533 | 285 |
534 enum ScopeType { | 286 enum ScopeType { |
535 kTopLevelScope, | 287 kTopLevelScope, |
536 kFunctionScope | 288 kFunctionScope |
537 }; | 289 }; |
538 | 290 |
539 enum VariableDeclarationContext { | 291 enum VariableDeclarationContext { |
540 kSourceElement, | 292 kSourceElement, |
541 kStatement, | 293 kStatement, |
542 kForStatement | 294 kForStatement |
543 }; | 295 }; |
544 | 296 |
545 // If a list of variable declarations includes any initializers. | 297 // If a list of variable declarations includes any initializers. |
546 enum VariableDeclarationProperties { | 298 enum VariableDeclarationProperties { |
547 kHasInitializers, | 299 kHasInitializers, |
548 kHasNoInitializers | 300 kHasNoInitializers |
549 }; | 301 }; |
550 | 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 |
551 class Statement { | 439 class Statement { |
552 public: | 440 public: |
553 static Statement Default() { | 441 static Statement Default() { |
554 return Statement(kUnknownStatement); | 442 return Statement(kUnknownStatement); |
555 } | 443 } |
556 | 444 |
557 static Statement FunctionDeclaration() { | 445 static Statement FunctionDeclaration() { |
558 return Statement(kFunctionDeclaration); | 446 return Statement(kFunctionDeclaration); |
559 } | 447 } |
560 | 448 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 Scope** const variable_; | 539 Scope** const variable_; |
652 Scope* const prev_; | 540 Scope* const prev_; |
653 const ScopeType type_; | 541 const ScopeType type_; |
654 int materialized_literal_count_; | 542 int materialized_literal_count_; |
655 int expected_properties_; | 543 int expected_properties_; |
656 int with_nesting_count_; | 544 int with_nesting_count_; |
657 LanguageMode language_mode_; | 545 LanguageMode language_mode_; |
658 bool is_generator_; | 546 bool is_generator_; |
659 }; | 547 }; |
660 | 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 |
661 // All ParseXXX functions take as the last argument an *ok parameter | 570 // All ParseXXX functions take as the last argument an *ok parameter |
662 // 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. |
663 // By making the 'exception handling' explicit, we are forced to check | 572 // By making the 'exception handling' explicit, we are forced to check |
664 // for failure at the call sites. | 573 // for failure at the call sites. |
665 Statement ParseSourceElement(bool* ok); | 574 Statement ParseSourceElement(bool* ok); |
666 SourceElements ParseSourceElements(int end_token, bool* ok); | 575 SourceElements ParseSourceElements(int end_token, bool* ok); |
667 Statement ParseStatement(bool* ok); | 576 Statement ParseStatement(bool* ok); |
668 Statement ParseFunctionDeclaration(bool* ok); | 577 Statement ParseFunctionDeclaration(bool* ok); |
669 Statement ParseBlock(bool* ok); | 578 Statement ParseBlock(bool* ok); |
670 Statement ParseVariableStatement(VariableDeclarationContext var_context, | 579 Statement ParseVariableStatement(VariableDeclarationContext var_context, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 | 615 |
707 Arguments ParseArguments(bool* ok); | 616 Arguments ParseArguments(bool* ok); |
708 Expression ParseFunctionLiteral( | 617 Expression ParseFunctionLiteral( |
709 Identifier name, | 618 Identifier name, |
710 Scanner::Location function_name_location, | 619 Scanner::Location function_name_location, |
711 bool name_is_strict_reserved, | 620 bool name_is_strict_reserved, |
712 bool is_generator, | 621 bool is_generator, |
713 bool* ok); | 622 bool* ok); |
714 void ParseLazyFunctionLiteralBody(bool* ok); | 623 void ParseLazyFunctionLiteralBody(bool* ok); |
715 | 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 |
716 // 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. |
717 void LogSymbol(); | 634 void LogSymbol(); |
| 635 // Log the currently parsed identifier. |
| 636 Identifier GetIdentifierSymbol(); |
718 // Log the currently parsed string literal. | 637 // Log the currently parsed string literal. |
719 Expression GetStringSymbol(); | 638 Expression GetStringSymbol(); |
720 | 639 |
721 void set_language_mode(LanguageMode language_mode) { | 640 void set_language_mode(LanguageMode language_mode) { |
722 scope_->set_language_mode(language_mode); | 641 scope_->set_language_mode(language_mode); |
723 } | 642 } |
724 | 643 |
| 644 virtual bool is_classic_mode() { |
| 645 return scope_->language_mode() == CLASSIC_MODE; |
| 646 } |
| 647 |
725 bool is_extended_mode() { | 648 bool is_extended_mode() { |
726 return scope_->language_mode() == EXTENDED_MODE; | 649 return scope_->language_mode() == EXTENDED_MODE; |
727 } | 650 } |
728 | 651 |
729 LanguageMode language_mode() { return scope_->language_mode(); } | 652 LanguageMode language_mode() { return scope_->language_mode(); } |
730 | 653 |
731 bool CheckInOrOf(bool accept_OF); | 654 bool CheckInOrOf(bool accept_OF); |
732 | 655 |
733 ParserRecorder* log_; | 656 ParserRecorder* log_; |
734 Scope* scope_; | 657 Scope* scope_; |
735 bool parenthesized_function_; | 658 bool parenthesized_function_; |
736 }; | 659 }; |
737 | 660 |
738 | |
739 template<class Traits> | |
740 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { | |
741 // We don't report stack overflows here, to avoid increasing the | |
742 // stack depth even further. Instead we report it after parsing is | |
743 // over, in ParseProgram. | |
744 if (token == Token::ILLEGAL && stack_overflow()) { | |
745 return; | |
746 } | |
747 Scanner::Location source_location = scanner()->location(); | |
748 | |
749 // Four of the tokens are treated specially | |
750 switch (token) { | |
751 case Token::EOS: | |
752 return ReportMessageAt(source_location, "unexpected_eos"); | |
753 case Token::NUMBER: | |
754 return ReportMessageAt(source_location, "unexpected_token_number"); | |
755 case Token::STRING: | |
756 return ReportMessageAt(source_location, "unexpected_token_string"); | |
757 case Token::IDENTIFIER: | |
758 return ReportMessageAt(source_location, "unexpected_token_identifier"); | |
759 case Token::FUTURE_RESERVED_WORD: | |
760 return ReportMessageAt(source_location, "unexpected_reserved"); | |
761 case Token::YIELD: | |
762 case Token::FUTURE_STRICT_RESERVED_WORD: | |
763 return ReportMessageAt( | |
764 source_location, | |
765 this->is_classic_mode() ? "unexpected_token_identifier" | |
766 : "unexpected_strict_reserved"); | |
767 default: | |
768 const char* name = Token::String(token); | |
769 ASSERT(name != NULL); | |
770 Traits::ReportMessageAt( | |
771 source_location, "unexpected_token", Vector<const char*>(&name, 1)); | |
772 } | |
773 } | |
774 | |
775 | |
776 template<class Traits> | |
777 typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifier( | |
778 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | |
779 bool* ok) { | |
780 Token::Value next = Next(); | |
781 if (next == Token::IDENTIFIER) { | |
782 typename Traits::IdentifierType name = this->GetSymbol(); | |
783 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | |
784 !this->is_classic_mode() && this->IsEvalOrArguments(name)) { | |
785 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); | |
786 *ok = false; | |
787 } | |
788 return name; | |
789 } else if (this->is_classic_mode() && | |
790 (next == Token::FUTURE_STRICT_RESERVED_WORD || | |
791 (next == Token::YIELD && !this->is_generator()))) { | |
792 return this->GetSymbol(); | |
793 } else { | |
794 this->ReportUnexpectedToken(next); | |
795 *ok = false; | |
796 return Traits::EmptyIdentifier(); | |
797 } | |
798 } | |
799 | |
800 | |
801 template <class Traits> | |
802 typename Traits::IdentifierType ParserBase< | |
803 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | |
804 bool* ok) { | |
805 Token::Value next = Next(); | |
806 if (next == Token::IDENTIFIER) { | |
807 *is_strict_reserved = false; | |
808 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || | |
809 (next == Token::YIELD && !this->is_generator())) { | |
810 *is_strict_reserved = true; | |
811 } else { | |
812 ReportUnexpectedToken(next); | |
813 *ok = false; | |
814 return Traits::EmptyIdentifier(); | |
815 } | |
816 return this->GetSymbol(); | |
817 } | |
818 | |
819 | |
820 template <class Traits> | |
821 typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifierName( | |
822 bool* ok) { | |
823 Token::Value next = Next(); | |
824 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && | |
825 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { | |
826 this->ReportUnexpectedToken(next); | |
827 *ok = false; | |
828 return Traits::EmptyIdentifier(); | |
829 } | |
830 return this->GetSymbol(); | |
831 } | |
832 | |
833 | |
834 template <class Traits> | |
835 typename Traits::IdentifierType | |
836 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, | |
837 bool* is_set, | |
838 bool* ok) { | |
839 typename Traits::IdentifierType result = ParseIdentifierName(ok); | |
840 if (!*ok) return Traits::EmptyIdentifier(); | |
841 if (scanner()->is_literal_ascii() && | |
842 scanner()->literal_length() == 3) { | |
843 const char* token = scanner()->literal_ascii_string().start(); | |
844 *is_get = strncmp(token, "get", 3) == 0; | |
845 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | |
846 } | |
847 return result; | |
848 } | |
849 | |
850 | |
851 template <typename Traits> | |
852 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | |
853 Token::Value property, | |
854 PropertyKind type, | |
855 bool* ok) { | |
856 int old; | |
857 if (property == Token::NUMBER) { | |
858 old = finder_.AddNumber(scanner()->literal_ascii_string(), type); | |
859 } else if (scanner()->is_literal_ascii()) { | |
860 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type); | |
861 } else { | |
862 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type); | |
863 } | |
864 PropertyKind old_type = static_cast<PropertyKind>(old); | |
865 if (HasConflict(old_type, type)) { | |
866 if (IsDataDataConflict(old_type, type)) { | |
867 // Both are data properties. | |
868 if (language_mode_ == CLASSIC_MODE) return; | |
869 parser()->ReportMessageAt(scanner()->location(), | |
870 "strict_duplicate_property"); | |
871 } else if (IsDataAccessorConflict(old_type, type)) { | |
872 // Both a data and an accessor property with the same name. | |
873 parser()->ReportMessageAt(scanner()->location(), | |
874 "accessor_data_property"); | |
875 } else { | |
876 ASSERT(IsAccessorAccessorConflict(old_type, type)); | |
877 // Both accessors of the same type. | |
878 parser()->ReportMessageAt(scanner()->location(), | |
879 "accessor_get_set"); | |
880 } | |
881 *ok = false; | |
882 } | |
883 } | |
884 | |
885 | |
886 } } // v8::internal | 661 } } // v8::internal |
887 | 662 |
888 #endif // V8_PREPARSER_H | 663 #endif // V8_PREPARSER_H |
OLD | NEW |