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

Side by Side Diff: src/preparser.h

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

Powered by Google App Engine
This is Rietveld 408576698