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

Side by Side Diff: src/preparser.h

Issue 158873006: Revert "Traitify ParserBase and move functions there." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
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 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
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
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
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
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
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
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
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