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