1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_PREPARSER_H 6 #define V8_PREPARSER_H 7 8 #include "src/v8.h" 9 10 #include "src/bailout-reason.h" 11 #include "src/func-name-inferrer.h" 12 #include "src/hashmap.h" 13 #include "src/scanner.h" 14 #include "src/scopes.h" 15 #include "src/token.h" 16 17 namespace v8 { 18 namespace internal { 19 20 // Common base class shared between parser and pre-parser. Traits encapsulate 21 // the differences between Parser and PreParser: 22 23 // - Return types: For example, Parser functions return Expression* and 24 // PreParser functions return PreParserExpression. 25 26 // - Creating parse tree nodes: Parser generates an AST during the recursive 27 // descent. PreParser doesn't create a tree. Instead, it passes around minimal 28 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain 29 // just enough data for the upper layer functions. PreParserFactory is 30 // responsible for creating these dummy objects. It provides a similar kind of 31 // interface as AstNodeFactory, so ParserBase doesn't need to care which one is 32 // used. 33 34 // - Miscellaneous other tasks interleaved with the recursive descent. For 35 // example, Parser keeps track of which function literals should be marked as 36 // pretenured, and PreParser doesn't care. 37 38 // The traits are expected to contain the following typedefs: 39 // struct Traits { 40 // // In particular... 41 // struct Type { 42 // // Used by FunctionState and BlockState. 43 // typedef Scope; 44 // typedef GeneratorVariable; 45 // typedef Zone; 46 // // Return types for traversing functions. 47 // typedef Identifier; 48 // typedef Expression; 49 // typedef FunctionLiteral; 50 // typedef ClassLiteral; 51 // typedef ObjectLiteralProperty; 52 // typedef Literal; 53 // typedef ExpressionList; 54 // typedef PropertyList; 55 // // For constructing objects returned by the traversing functions. 56 // typedef Factory; 57 // }; 58 // // ... 59 // }; 60 61 template <typename Traits> 62 class ParserBase : public Traits { 63 public: 64 // Shorten type names defined by Traits. 65 typedef typename Traits::Type::Expression ExpressionT; 66 typedef typename Traits::Type::Identifier IdentifierT; 67 typedef typename Traits::Type::FunctionLiteral FunctionLiteralT; 68 typedef typename Traits::Type::Literal LiteralT; 69 typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT; 70 71 ParserBase(Scanner* scanner, uintptr_t stack_limit, v8::Extension* extension, 72 ParserRecorder* log, typename Traits::Type::Zone* zone, 73 AstNode::IdGen* ast_node_id_gen, 74 typename Traits::Type::Parser this_object) 75 : Traits(this_object), 76 parenthesized_function_(false), 77 scope_(NULL), 78 function_state_(NULL), 79 extension_(extension), 80 fni_(NULL), 81 log_(log), 82 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. 83 stack_limit_(stack_limit), 84 scanner_(scanner), 85 stack_overflow_(false), 86 allow_lazy_(false), 87 allow_natives_syntax_(false), 88 allow_arrow_functions_(false), 89 allow_harmony_object_literals_(false), 90 zone_(zone), 91 ast_node_id_gen_(ast_node_id_gen) {} 92 93 // Getters that indicate whether certain syntactical constructs are 94 // allowed to be parsed by this instance of the parser. 95 bool allow_lazy() const { return allow_lazy_; } 96 bool allow_natives_syntax() const { return allow_natives_syntax_; } 97 bool allow_arrow_functions() const { return allow_arrow_functions_; } 98 bool allow_modules() const { return scanner()->HarmonyModules(); } 99 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } 100 bool allow_harmony_numeric_literals() const { 101 return scanner()->HarmonyNumericLiterals(); 102 } 103 bool allow_classes() const { return scanner()->HarmonyClasses(); } 104 bool allow_harmony_object_literals() const { 105 return allow_harmony_object_literals_; 106 } 107 108 // Setters that determine whether certain syntactical constructs are 109 // allowed to be parsed by this instance of the parser. 110 void set_allow_lazy(bool allow) { allow_lazy_ = allow; } 111 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; } 112 void set_allow_arrow_functions(bool allow) { allow_arrow_functions_ = allow; } 113 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); } 114 void set_allow_harmony_scoping(bool allow) { 115 scanner()->SetHarmonyScoping(allow); 116 } 117 void set_allow_harmony_numeric_literals(bool allow) { 118 scanner()->SetHarmonyNumericLiterals(allow); 119 } 120 void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); } 121 void set_allow_harmony_object_literals(bool allow) { 122 allow_harmony_object_literals_ = allow; 123 } 124 125 protected: 126 friend class Traits::Checkpoint; 127 128 enum AllowEvalOrArgumentsAsIdentifier { 129 kAllowEvalOrArguments, 130 kDontAllowEvalOrArguments 131 }; 132 133 enum Mode { 134 PARSE_LAZILY, 135 PARSE_EAGERLY 136 }; 137 138 class CheckpointBase; 139 class ObjectLiteralChecker; 140 141 // --------------------------------------------------------------------------- 142 // FunctionState and BlockState together implement the parser's scope stack. 143 // The parser's current scope is in scope_. BlockState and FunctionState 144 // constructors push on the scope stack and the destructors pop. They are also 145 // used to hold the parser's per-function and per-block state. 146 class BlockState BASE_EMBEDDED { 147 public: 148 BlockState(typename Traits::Type::Scope** scope_stack, 149 typename Traits::Type::Scope* scope) 150 : scope_stack_(scope_stack), 151 outer_scope_(*scope_stack), 152 scope_(scope) { 153 *scope_stack_ = scope_; 154 } 155 ~BlockState() { *scope_stack_ = outer_scope_; } 156 157 private: 158 typename Traits::Type::Scope** scope_stack_; 159 typename Traits::Type::Scope* outer_scope_; 160 typename Traits::Type::Scope* scope_; 161 }; 162 163 class FunctionState BASE_EMBEDDED { 164 public: 165 FunctionState(FunctionState** function_state_stack, 166 typename Traits::Type::Scope** scope_stack, 167 typename Traits::Type::Scope* scope, 168 typename Traits::Type::Zone* zone = NULL, 169 AstValueFactory* ast_value_factory = NULL, 170 AstNode::IdGen* ast_node_id_gen = NULL); 171 FunctionState(FunctionState** function_state_stack, 172 typename Traits::Type::Scope** scope_stack, 173 typename Traits::Type::Scope** scope, 174 typename Traits::Type::Zone* zone = NULL, 175 AstValueFactory* ast_value_factory = NULL, 176 AstNode::IdGen* ast_node_id_gen = NULL); 177 ~FunctionState(); 178 179 int NextMaterializedLiteralIndex() { 180 return next_materialized_literal_index_++; 181 } 182 int materialized_literal_count() { 183 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize; 184 } 185 186 int NextHandlerIndex() { return next_handler_index_++; } 187 int handler_count() { return next_handler_index_; } 188 189 void AddProperty() { expected_property_count_++; } 190 int expected_property_count() { return expected_property_count_; } 191 192 void set_is_generator(bool is_generator) { is_generator_ = is_generator; } 193 bool is_generator() const { return is_generator_; } 194 195 void set_generator_object_variable( 196 typename Traits::Type::GeneratorVariable* variable) { 197 DCHECK(variable != NULL); 198 DCHECK(!is_generator()); 199 generator_object_variable_ = variable; 200 is_generator_ = true; 201 } 202 typename Traits::Type::GeneratorVariable* generator_object_variable() 203 const { 204 return generator_object_variable_; 205 } 206 207 typename Traits::Type::Factory* factory() { return &factory_; } 208 209 private: 210 // Used to assign an index to each literal that needs materialization in 211 // the function. Includes regexp literals, and boilerplate for object and 212 // array literals. 213 int next_materialized_literal_index_; 214 215 // Used to assign a per-function index to try and catch handlers. 216 int next_handler_index_; 217 218 // Properties count estimation. 219 int expected_property_count_; 220 221 // Whether the function is a generator. 222 bool is_generator_; 223 // For generators, this variable may hold the generator object. It variable 224 // is used by yield expressions and return statements. It is not necessary 225 // for generator functions to have this variable set. 226 Variable* generator_object_variable_; 227 228 FunctionState** function_state_stack_; 229 FunctionState* outer_function_state_; 230 typename Traits::Type::Scope** scope_stack_; 231 typename Traits::Type::Scope* outer_scope_; 232 AstNode::IdGen* ast_node_id_gen_; // Only used by ParserTraits. 233 AstNode::IdGen saved_id_gen_; // Ditto. 234 typename Traits::Type::Zone* extra_param_; 235 typename Traits::Type::Factory factory_; 236 237 friend class ParserTraits; 238 friend class CheckpointBase; 239 }; 240 241 // Annoyingly, arrow functions first parse as comma expressions, then when we 242 // see the => we have to go back and reinterpret the arguments as being formal 243 // parameters. To do so we need to reset some of the parser state back to 244 // what it was before the arguments were first seen. 245 class CheckpointBase BASE_EMBEDDED { 246 public: 247 explicit CheckpointBase(ParserBase* parser) { 248 function_state_ = parser->function_state_; 249 next_materialized_literal_index_ = 250 function_state_->next_materialized_literal_index_; 251 next_handler_index_ = function_state_->next_handler_index_; 252 expected_property_count_ = function_state_->expected_property_count_; 253 } 254 255 void Restore() { 256 function_state_->next_materialized_literal_index_ = 257 next_materialized_literal_index_; 258 function_state_->next_handler_index_ = next_handler_index_; 259 function_state_->expected_property_count_ = expected_property_count_; 260 } 261 262 private: 263 FunctionState* function_state_; 264 int next_materialized_literal_index_; 265 int next_handler_index_; 266 int expected_property_count_; 267 }; 268 269 class ParsingModeScope BASE_EMBEDDED { 270 public: 271 ParsingModeScope(ParserBase* parser, Mode mode) 272 : parser_(parser), 273 old_mode_(parser->mode()) { 274 parser_->mode_ = mode; 275 } 276 ~ParsingModeScope() { 277 parser_->mode_ = old_mode_; 278 } 279 280 private: 281 ParserBase* parser_; 282 Mode old_mode_; 283 }; 284 285 Scanner* scanner() const { return scanner_; } 286 int position() { return scanner_->location().beg_pos; } 287 int peek_position() { return scanner_->peek_location().beg_pos; } 288 bool stack_overflow() const { return stack_overflow_; } 289 void set_stack_overflow() { stack_overflow_ = true; } 290 Mode mode() const { return mode_; } 291 typename Traits::Type::Zone* zone() const { return zone_; } 292 AstNode::IdGen* ast_node_id_gen() const { return ast_node_id_gen_; } 293 294 INLINE(Token::Value peek()) { 295 if (stack_overflow_) return Token::ILLEGAL; 296 return scanner()->peek(); 297 } 298 299 INLINE(Token::Value Next()) { 300 if (stack_overflow_) return Token::ILLEGAL; 301 { 302 if (GetCurrentStackPosition() < stack_limit_) { 303 // Any further calls to Next or peek will return the illegal token. 304 // The current call must return the next token, which might already 305 // have been peek'ed. 306 stack_overflow_ = true; 307 } 308 } 309 return scanner()->Next(); 310 } 311 312 void Consume(Token::Value token) { 313 Token::Value next = Next(); 314 USE(next); 315 USE(token); 316 DCHECK(next == token); 317 } 318 319 bool Check(Token::Value token) { 320 Token::Value next = peek(); 321 if (next == token) { 322 Consume(next); 323 return true; 324 } 325 return false; 326 } 327 328 void Expect(Token::Value token, bool* ok) { 329 Token::Value next = Next(); 330 if (next != token) { 331 ReportUnexpectedToken(next); 332 *ok = false; 333 } 334 } 335 336 void ExpectSemicolon(bool* ok) { 337 // Check for automatic semicolon insertion according to 338 // the rules given in ECMA-262, section 7.9, page 21. 339 Token::Value tok = peek(); 340 if (tok == Token::SEMICOLON) { 341 Next(); 342 return; 343 } 344 if (scanner()->HasAnyLineTerminatorBeforeNext() || 345 tok == Token::RBRACE || 346 tok == Token::EOS) { 347 return; 348 } 349 Expect(Token::SEMICOLON, ok); 350 } 351 352 bool peek_any_identifier() { 353 Token::Value next = peek(); 354 return next == Token::IDENTIFIER || 355 next == Token::FUTURE_RESERVED_WORD || 356 next == Token::FUTURE_STRICT_RESERVED_WORD || 357 next == Token::LET || 358 next == Token::YIELD; 359 } 360 361 bool CheckContextualKeyword(Vector<const char> keyword) { 362 if (peek() == Token::IDENTIFIER && 363 scanner()->is_next_contextual_keyword(keyword)) { 364 Consume(Token::IDENTIFIER); 365 return true; 366 } 367 return false; 368 } 369 370 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { 371 Expect(Token::IDENTIFIER, ok); 372 if (!*ok) return; 373 if (!scanner()->is_literal_contextual_keyword(keyword)) { 374 ReportUnexpectedToken(scanner()->current_token()); 375 *ok = false; 376 } 377 } 378 379 // Checks whether an octal literal was last seen between beg_pos and end_pos. 380 // If so, reports an error. Only called for strict mode. 381 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { 382 Scanner::Location octal = scanner()->octal_position(); 383 if (octal.IsValid() && beg_pos <= octal.beg_pos && 384 octal.end_pos <= end_pos) { 385 ReportMessageAt(octal, "strict_octal_literal"); 386 scanner()->clear_octal_position(); 387 *ok = false; 388 } 389 } 390 391 // Validates strict mode for function parameter lists. This has to be 392 // done after parsing the function, since the function can declare 393 // itself strict. 394 void CheckStrictFunctionNameAndParameters( 395 IdentifierT function_name, 396 bool function_name_is_strict_reserved, 397 const Scanner::Location& function_name_loc, 398 const Scanner::Location& eval_args_error_loc, 399 const Scanner::Location& dupe_error_loc, 400 const Scanner::Location& reserved_loc, 401 bool* ok) { 402 if (this->IsEvalOrArguments(function_name)) { 403 Traits::ReportMessageAt(function_name_loc, "strict_eval_arguments"); 404 *ok = false; 405 return; 406 } 407 if (function_name_is_strict_reserved) { 408 Traits::ReportMessageAt(function_name_loc, "unexpected_strict_reserved"); 409 *ok = false; 410 return; 411 } 412 if (eval_args_error_loc.IsValid()) { 413 Traits::ReportMessageAt(eval_args_error_loc, "strict_eval_arguments"); 414 *ok = false; 415 return; 416 } 417 if (dupe_error_loc.IsValid()) { 418 Traits::ReportMessageAt(dupe_error_loc, "strict_param_dupe"); 419 *ok = false; 420 return; 421 } 422 if (reserved_loc.IsValid()) { 423 Traits::ReportMessageAt(reserved_loc, "unexpected_strict_reserved"); 424 *ok = false; 425 return; 426 } 427 } 428 429 // Determine precedence of given token. 430 static int Precedence(Token::Value token, bool accept_IN) { 431 if (token == Token::IN && !accept_IN) 432 return 0; // 0 precedence will terminate binary expression parsing 433 return Token::Precedence(token); 434 } 435 436 typename Traits::Type::Factory* factory() { 437 return function_state_->factory(); 438 } 439 440 StrictMode strict_mode() { return scope_->strict_mode(); } 441 bool is_generator() const { return function_state_->is_generator(); } 442 443 // Report syntax errors. 444 void ReportMessage(const char* message, const char* arg = NULL, 445 bool is_reference_error = false) { 446 Scanner::Location source_location = scanner()->location(); 447 Traits::ReportMessageAt(source_location, message, arg, is_reference_error); 448 } 449 450 void ReportMessageAt(Scanner::Location location, const char* message, 451 bool is_reference_error = false) { 452 Traits::ReportMessageAt(location, message, 453 reinterpret_cast<const char*>(NULL), 454 is_reference_error); 455 } 456 457 void ReportUnexpectedToken(Token::Value token); 458 459 // Recursive descent functions: 460 461 // Parses an identifier that is valid for the current scope, in particular it 462 // fails on strict mode future reserved keywords in a strict scope. If 463 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or 464 // "arguments" as identifier even in strict mode (this is needed in cases like 465 // "var foo = eval;"). 466 IdentifierT ParseIdentifier( 467 AllowEvalOrArgumentsAsIdentifier, 468 bool* ok); 469 // Parses an identifier or a strict mode future reserved word, and indicate 470 // whether it is strict mode future reserved. 471 IdentifierT ParseIdentifierOrStrictReservedWord( 472 bool* is_strict_reserved, 473 bool* ok); 474 IdentifierT ParseIdentifierName(bool* ok); 475 // Parses an identifier and determines whether or not it is 'get' or 'set'. 476 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, 477 bool* is_set, 478 bool* ok); 479 480 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok); 481 482 ExpressionT ParsePrimaryExpression(bool* ok); 483 ExpressionT ParseExpression(bool accept_IN, bool* ok); 484 ExpressionT ParseArrayLiteral(bool* ok); 485 IdentifierT ParsePropertyName(bool* is_get, bool* is_set, bool* is_static, 486 bool* ok); 487 ExpressionT ParseObjectLiteral(bool* ok); 488 ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker, 489 bool in_class, bool is_static, 490 bool* ok); 491 typename Traits::Type::ExpressionList ParseArguments(bool* ok); 492 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); 493 ExpressionT ParseYieldExpression(bool* ok); 494 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); 495 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); 496 ExpressionT ParseUnaryExpression(bool* ok); 497 ExpressionT ParsePostfixExpression(bool* ok); 498 ExpressionT ParseLeftHandSideExpression(bool* ok); 499 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); 500 ExpressionT ParseMemberExpression(bool* ok); 501 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, 502 bool* ok); 503 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, 504 bool* ok); 505 ExpressionT ParseClassLiteral(IdentifierT name, 506 Scanner::Location function_name_location, 507 bool name_is_strict_reserved, int pos, 508 bool* ok); 509 510 // Checks if the expression is a valid reference expression (e.g., on the 511 // left-hand side of assignments). Although ruled out by ECMA as early errors, 512 // we allow calls for web compatibility and rewrite them to a runtime throw. 513 ExpressionT CheckAndRewriteReferenceExpression( 514 ExpressionT expression, 515 Scanner::Location location, const char* message, bool* ok); 516 517 // Used to detect duplicates in object literals. Each of the values 518 // kGetterProperty, kSetterProperty and kValueProperty represents 519 // a type of object literal property. When parsing a property, its 520 // type value is stored in the DuplicateFinder for the property name. 521 // Values are chosen so that having intersection bits means the there is 522 // an incompatibility. 523 // I.e., you can add a getter to a property that already has a setter, since 524 // kGetterProperty and kSetterProperty doesn't intersect, but not if it 525 // already has a getter or a value. Adding the getter to an existing 526 // setter will store the value (kGetterProperty | kSetterProperty), which 527 // is incompatible with adding any further properties. 528 enum PropertyKind { 529 kNone = 0, 530 // Bit patterns representing different object literal property types. 531 kGetterProperty = 1, 532 kSetterProperty = 2, 533 kValueProperty = 7, 534 // Helper constants. 535 kValueFlag = 4 536 }; 537 538 // Validation per ECMA 262 - 11.1.5 "Object Initializer". 539 class ObjectLiteralChecker { 540 public: 541 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode) 542 : parser_(parser), 543 finder_(scanner()->unicode_cache()), 544 strict_mode_(strict_mode) {} 545 546 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); 547 548 private: 549 ParserBase* parser() const { return parser_; } 550 Scanner* scanner() const { return parser_->scanner(); } 551 552 // Checks the type of conflict based on values coming from PropertyType. 553 bool HasConflict(PropertyKind type1, PropertyKind type2) { 554 return (type1 & type2) != 0; 555 } 556 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { 557 return ((type1 & type2) & kValueFlag) != 0; 558 } 559 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { 560 return ((type1 ^ type2) & kValueFlag) != 0; 561 } 562 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { 563 return ((type1 | type2) & kValueFlag) == 0; 564 } 565 566 ParserBase* parser_; 567 DuplicateFinder finder_; 568 StrictMode strict_mode_; 569 }; 570 571 // If true, the next (and immediately following) function literal is 572 // preceded by a parenthesis. 573 // Heuristically that means that the function will be called immediately, 574 // so never lazily compile it. 575 bool parenthesized_function_; 576 577 typename Traits::Type::Scope* scope_; // Scope stack. 578 FunctionState* function_state_; // Function state stack. 579 v8::Extension* extension_; 580 FuncNameInferrer* fni_; 581 ParserRecorder* log_; 582 Mode mode_; 583 uintptr_t stack_limit_; 584 585 private: 586 Scanner* scanner_; 587 bool stack_overflow_; 588 589 bool allow_lazy_; 590 bool allow_natives_syntax_; 591 bool allow_arrow_functions_; 592 bool allow_harmony_object_literals_; 593 594 typename Traits::Type::Zone* zone_; // Only used by Parser. 595 AstNode::IdGen* ast_node_id_gen_; 596 }; 597 598 599 class PreParserIdentifier { 600 public: 601 PreParserIdentifier() : type_(kUnknownIdentifier) {} 602 static PreParserIdentifier Default() { 603 return PreParserIdentifier(kUnknownIdentifier); 604 } 605 static PreParserIdentifier Eval() { 606 return PreParserIdentifier(kEvalIdentifier); 607 } 608 static PreParserIdentifier Arguments() { 609 return PreParserIdentifier(kArgumentsIdentifier); 610 } 611 static PreParserIdentifier FutureReserved() { 612 return PreParserIdentifier(kFutureReservedIdentifier); 613 } 614 static PreParserIdentifier FutureStrictReserved() { 615 return PreParserIdentifier(kFutureStrictReservedIdentifier); 616 } 617 static PreParserIdentifier Let() { 618 return PreParserIdentifier(kLetIdentifier); 619 } 620 static PreParserIdentifier Yield() { 621 return PreParserIdentifier(kYieldIdentifier); 622 } 623 static PreParserIdentifier Prototype() { 624 return PreParserIdentifier(kPrototypeIdentifier); 625 } 626 static PreParserIdentifier Constructor() { 627 return PreParserIdentifier(kConstructorIdentifier); 628 } 629 bool IsEval() const { return type_ == kEvalIdentifier; } 630 bool IsArguments() const { return type_ == kArgumentsIdentifier; } 631 bool IsYield() const { return type_ == kYieldIdentifier; } 632 bool IsPrototype() const { return type_ == kPrototypeIdentifier; } 633 bool IsConstructor() const { return type_ == kConstructorIdentifier; } 634 bool IsEvalOrArguments() const { 635 return type_ == kEvalIdentifier || type_ == kArgumentsIdentifier; 636 } 637 bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } 638 bool IsFutureStrictReserved() const { 639 return type_ == kFutureStrictReservedIdentifier; 640 } 641 bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; } 642 643 // Allow identifier->name()[->length()] to work. The preparser 644 // does not need the actual positions/lengths of the identifiers. 645 const PreParserIdentifier* operator->() const { return this; } 646 const PreParserIdentifier raw_name() const { return *this; } 647 648 int position() const { return 0; } 649 int length() const { return 0; } 650 651 private: 652 enum Type { 653 kUnknownIdentifier, 654 kFutureReservedIdentifier, 655 kFutureStrictReservedIdentifier, 656 kLetIdentifier, 657 kYieldIdentifier, 658 kEvalIdentifier, 659 kArgumentsIdentifier, 660 kPrototypeIdentifier, 661 kConstructorIdentifier 662 }; 663 explicit PreParserIdentifier(Type type) : type_(type) {} 664 Type type_; 665 666 friend class PreParserExpression; 667 friend class PreParserScope; 668 }; 669 670 671 // Bits 0 and 1 are used to identify the type of expression: 672 // If bit 0 is set, it's an identifier. 673 // if bit 1 is set, it's a string literal. 674 // If neither is set, it's no particular type, and both set isn't 675 // use yet. 676 class PreParserExpression { 677 public: 678 static PreParserExpression Default() { 679 return PreParserExpression(kUnknownExpression); 680 } 681 682 static PreParserExpression FromIdentifier(PreParserIdentifier id) { 683 return PreParserExpression(kTypeIdentifier | 684 (id.type_ << kIdentifierShift)); 685 } 686 687 static PreParserExpression BinaryOperation(PreParserExpression left, 688 Token::Value op, 689 PreParserExpression right) { 690 int code = ((op == Token::COMMA) && !left.is_parenthesized() && 691 !right.is_parenthesized()) 692 ? left.ArrowParamListBit() & right.ArrowParamListBit() 693 : 0; 694 return PreParserExpression(kTypeBinaryOperation | code); 695 } 696 697 static PreParserExpression EmptyArrowParamList() { 698 // Any expression for which IsValidArrowParamList() returns true 699 // will work here. 700 return FromIdentifier(PreParserIdentifier::Default()); 701 } 702 703 static PreParserExpression StringLiteral() { 704 return PreParserExpression(kUnknownStringLiteral); 705 } 706 707 static PreParserExpression UseStrictStringLiteral() { 708 return PreParserExpression(kUseStrictString); 709 } 710 711 static PreParserExpression This() { 712 return PreParserExpression(kThisExpression); 713 } 714 715 static PreParserExpression Super() { 716 return PreParserExpression(kSuperExpression); 717 } 718 719 static PreParserExpression ThisProperty() { 720 return PreParserExpression(kThisPropertyExpression); 721 } 722 723 static PreParserExpression Property() { 724 return PreParserExpression(kPropertyExpression); 725 } 726 727 static PreParserExpression Call() { 728 return PreParserExpression(kCallExpression); 729 } 730 731 bool IsIdentifier() const { return (code_ & kTypeMask) == kTypeIdentifier; } 732 733 PreParserIdentifier AsIdentifier() const { 734 DCHECK(IsIdentifier()); 735 return PreParserIdentifier( 736 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); 737 } 738 739 bool IsStringLiteral() const { 740 return (code_ & kTypeMask) == kTypeStringLiteral; 741 } 742 743 bool IsUseStrictLiteral() const { 744 return (code_ & kUseStrictString) == kUseStrictString; 745 } 746 747 bool IsThis() const { return (code_ & kThisExpression) == kThisExpression; } 748 749 bool IsThisProperty() const { 750 return (code_ & kThisPropertyExpression) == kThisPropertyExpression; 751 } 752 753 bool IsProperty() const { 754 return (code_ & kPropertyExpression) == kPropertyExpression || 755 (code_ & kThisPropertyExpression) == kThisPropertyExpression; 756 } 757 758 bool IsCall() const { return (code_ & kCallExpression) == kCallExpression; } 759 760 bool IsValidReferenceExpression() const { 761 return IsIdentifier() || IsProperty(); 762 } 763 764 bool IsValidArrowParamList() const { 765 return (ArrowParamListBit() & kBinaryOperationArrowParamList) != 0 && 766 (code_ & kMultiParenthesizedExpression) == 0; 767 } 768 769 // At the moment PreParser doesn't track these expression types. 770 bool IsFunctionLiteral() const { return false; } 771 bool IsCallNew() const { return false; } 772 773 PreParserExpression AsFunctionLiteral() { return *this; } 774 775 bool IsBinaryOperation() const { 776 return (code_ & kTypeMask) == kTypeBinaryOperation; 777 } 778 779 bool is_parenthesized() const { 780 return (code_ & kParenthesizedExpression) != 0; 781 } 782 783 void increase_parenthesization_level() { 784 code_ |= is_parenthesized() ? kMultiParenthesizedExpression 785 : kParenthesizedExpression; 786 } 787 788 // Dummy implementation for making expression->somefunc() work in both Parser 789 // and PreParser. 790 PreParserExpression* operator->() { return this; } 791 792 // More dummy implementations of things PreParser doesn't need to track: 793 void set_index(int index) {} // For YieldExpressions 794 void set_parenthesized() {} 795 796 int position() const { return RelocInfo::kNoPosition; } 797 void set_function_token_position(int position) {} 798 void set_ast_properties(int* ast_properties) {} 799 void set_dont_optimize_reason(BailoutReason dont_optimize_reason) {} 800 801 bool operator==(const PreParserExpression& other) const { 802 return code_ == other.code_; 803 } 804 bool operator!=(const PreParserExpression& other) const { 805 return code_ != other.code_; 806 } 807 808 private: 809 // Least significant 2 bits are used as expression type. The third least 810 // significant bit tracks whether an expression is parenthesized. If the 811 // expression is an identifier or a string literal, the other bits 812 // describe the type/ (see PreParserIdentifier::Type and string literal 813 // constants below). For binary operations, the other bits are flags 814 // which further describe the contents of the expression. 815 enum { 816 kUnknownExpression = 0, 817 kTypeMask = 1 | 2, 818 kParenthesizedExpression = (1 << 2), 819 kMultiParenthesizedExpression = (1 << 3), 820 821 // Identifiers 822 kTypeIdentifier = 1, // Used to detect labels. 823 kIdentifierShift = 5, 824 kTypeStringLiteral = 2, // Used to detect directive prologue. 825 kUnknownStringLiteral = kTypeStringLiteral, 826 kUseStrictString = kTypeStringLiteral | 32, 827 kStringLiteralMask = kUseStrictString, 828 829 // Binary operations. Those are needed to detect certain keywords and 830 // duplicated identifier in parameter lists for arrow functions, because 831 // they are initially parsed as comma-separated expressions. 832 kTypeBinaryOperation = 3, 833 kBinaryOperationArrowParamList = (1 << 4), 834 835 // Below here applies if neither identifier nor string literal. Reserve the 836 // 2 least significant bits for flags. 837 kThisExpression = (1 << 4), 838 kThisPropertyExpression = (2 << 4), 839 kPropertyExpression = (3 << 4), 840 kCallExpression = (4 << 4), 841 kSuperExpression = (5 << 4) 842 }; 843 844 explicit PreParserExpression(int expression_code) : code_(expression_code) {} 845 846 V8_INLINE int ArrowParamListBit() const { 847 if (IsBinaryOperation()) return code_ & kBinaryOperationArrowParamList; 848 if (IsIdentifier()) { 849 const PreParserIdentifier ident = AsIdentifier(); 850 // A valid identifier can be an arrow function parameter list 851 // except for eval, arguments, yield, and reserved keywords. 852 if (ident.IsEval() || ident.IsArguments() || ident.IsYield() || 853 ident.IsFutureStrictReserved()) 854 return 0; 855 return kBinaryOperationArrowParamList; 856 } 857 return 0; 858 } 859 860 int code_; 861 }; 862 863 864 // PreParserExpressionList doesn't actually store the expressions because 865 // PreParser doesn't need to. 866 class PreParserExpressionList { 867 public: 868 // These functions make list->Add(some_expression) work (and do nothing). 869 PreParserExpressionList() : length_(0) {} 870 PreParserExpressionList* operator->() { return this; } 871 void Add(PreParserExpression, void*) { ++length_; } 872 int length() const { return length_; } 873 private: 874 int length_; 875 }; 876 877 878 class PreParserStatement { 879 public: 880 static PreParserStatement Default() { 881 return PreParserStatement(kUnknownStatement); 882 } 883 884 static PreParserStatement FunctionDeclaration() { 885 return PreParserStatement(kFunctionDeclaration); 886 } 887 888 // Creates expression statement from expression. 889 // Preserves being an unparenthesized string literal, possibly 890 // "use strict". 891 static PreParserStatement ExpressionStatement( 892 PreParserExpression expression) { 893 if (expression.IsUseStrictLiteral()) { 894 return PreParserStatement(kUseStrictExpressionStatement); 895 } 896 if (expression.IsStringLiteral()) { 897 return PreParserStatement(kStringLiteralExpressionStatement); 898 } 899 return Default(); 900 } 901 902 bool IsStringLiteral() { 903 return code_ == kStringLiteralExpressionStatement; 904 } 905 906 bool IsUseStrictLiteral() { 907 return code_ == kUseStrictExpressionStatement; 908 } 909 910 bool IsFunctionDeclaration() { 911 return code_ == kFunctionDeclaration; 912 } 913 914 private: 915 enum Type { 916 kUnknownStatement, 917 kStringLiteralExpressionStatement, 918 kUseStrictExpressionStatement, 919 kFunctionDeclaration 920 }; 921 922 explicit PreParserStatement(Type code) : code_(code) {} 923 Type code_; 924 }; 925 926 927 928 // PreParserStatementList doesn't actually store the statements because 929 // the PreParser does not need them. 930 class PreParserStatementList { 931 public: 932 // These functions make list->Add(some_expression) work as no-ops. 933 PreParserStatementList() {} 934 PreParserStatementList* operator->() { return this; } 935 void Add(PreParserStatement, void*) {} 936 }; 937 938 939 class PreParserScope { 940 public: 941 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type, 942 void* = NULL) 943 : scope_type_(scope_type) { 944 strict_mode_ = outer_scope ? outer_scope->strict_mode() : SLOPPY; 945 } 946 947 ScopeType type() { return scope_type_; } 948 StrictMode strict_mode() const { return strict_mode_; } 949 void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; } 950 void SetScopeName(PreParserIdentifier name) {} 951 952 // When PreParser is in use, lazy compilation is already being done, 953 // things cannot get lazier than that. 954 bool AllowsLazyCompilation() const { return false; } 955 956 void set_start_position(int position) {} 957 void set_end_position(int position) {} 958 959 bool IsDeclared(const PreParserIdentifier& identifier) const { return false; } 960 void DeclareParameter(const PreParserIdentifier& identifier, VariableMode) {} 961 962 // Allow scope->Foo() to work. 963 PreParserScope* operator->() { return this; } 964 965 private: 966 ScopeType scope_type_; 967 StrictMode strict_mode_; 968 }; 969 970 971 class PreParserFactory { 972 public: 973 PreParserFactory(void*, void*, void*) {} 974 PreParserExpression NewStringLiteral(PreParserIdentifier identifier, 975 int pos) { 976 return PreParserExpression::Default(); 977 } 978 PreParserExpression NewNumberLiteral(double number, 979 int pos) { 980 return PreParserExpression::Default(); 981 } 982 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, 983 PreParserIdentifier js_flags, 984 int literal_index, 985 int pos) { 986 return PreParserExpression::Default(); 987 } 988 PreParserExpression NewArrayLiteral(PreParserExpressionList values, 989 int literal_index, 990 int pos) { 991 return PreParserExpression::Default(); 992 } 993 PreParserExpression NewObjectLiteralProperty(bool is_getter, 994 PreParserExpression value, 995 int pos, bool is_static) { 996 return PreParserExpression::Default(); 997 } 998 PreParserExpression NewObjectLiteralProperty(PreParserExpression key, 999 PreParserExpression value, 1000 bool is_static) { 1001 return PreParserExpression::Default(); 1002 } 1003 PreParserExpression NewObjectLiteral(PreParserExpressionList properties, 1004 int literal_index, 1005 int boilerplate_properties, 1006 bool has_function, 1007 int pos) { 1008 return PreParserExpression::Default(); 1009 } 1010 PreParserExpression NewVariableProxy(void* variable) { 1011 return PreParserExpression::Default(); 1012 } 1013 PreParserExpression NewProperty(PreParserExpression obj, 1014 PreParserExpression key, 1015 int pos) { 1016 if (obj.IsThis()) { 1017 return PreParserExpression::ThisProperty(); 1018 } 1019 return PreParserExpression::Property(); 1020 } 1021 PreParserExpression NewUnaryOperation(Token::Value op, 1022 PreParserExpression expression, 1023 int pos) { 1024 return PreParserExpression::Default(); 1025 } 1026 PreParserExpression NewBinaryOperation(Token::Value op, 1027 PreParserExpression left, 1028 PreParserExpression right, int pos) { 1029 return PreParserExpression::BinaryOperation(left, op, right); 1030 } 1031 PreParserExpression NewCompareOperation(Token::Value op, 1032 PreParserExpression left, 1033 PreParserExpression right, int pos) { 1034 return PreParserExpression::Default(); 1035 } 1036 PreParserExpression NewAssignment(Token::Value op, 1037 PreParserExpression left, 1038 PreParserExpression right, 1039 int pos) { 1040 return PreParserExpression::Default(); 1041 } 1042 PreParserExpression NewYield(PreParserExpression generator_object, 1043 PreParserExpression expression, 1044 Yield::Kind yield_kind, 1045 int pos) { 1046 return PreParserExpression::Default(); 1047 } 1048 PreParserExpression NewConditional(PreParserExpression condition, 1049 PreParserExpression then_expression, 1050 PreParserExpression else_expression, 1051 int pos) { 1052 return PreParserExpression::Default(); 1053 } 1054 PreParserExpression NewCountOperation(Token::Value op, 1055 bool is_prefix, 1056 PreParserExpression expression, 1057 int pos) { 1058 return PreParserExpression::Default(); 1059 } 1060 PreParserExpression NewCall(PreParserExpression expression, 1061 PreParserExpressionList arguments, 1062 int pos) { 1063 return PreParserExpression::Call(); 1064 } 1065 PreParserExpression NewCallNew(PreParserExpression expression, 1066 PreParserExpressionList arguments, 1067 int pos) { 1068 return PreParserExpression::Default(); 1069 } 1070 PreParserStatement NewReturnStatement(PreParserExpression expression, 1071 int pos) { 1072 return PreParserStatement::Default(); 1073 } 1074 PreParserExpression NewFunctionLiteral( 1075 PreParserIdentifier name, AstValueFactory* ast_value_factory, 1076 const PreParserScope& scope, PreParserStatementList body, 1077 int materialized_literal_count, int expected_property_count, 1078 int handler_count, int parameter_count, 1079 FunctionLiteral::ParameterFlag has_duplicate_parameters, 1080 FunctionLiteral::FunctionType function_type, 1081 FunctionLiteral::IsFunctionFlag is_function, 1082 FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind, 1083 int position) { 1084 return PreParserExpression::Default(); 1085 } 1086 PreParserExpression NewClassLiteral(PreParserIdentifier name, 1087 PreParserExpression extends, 1088 PreParserExpression constructor, 1089 PreParserExpressionList properties, 1090 int position) { 1091 return PreParserExpression::Default(); 1092 } 1093 1094 // Return the object itself as AstVisitor and implement the needed 1095 // dummy method right in this class. 1096 PreParserFactory* visitor() { return this; } 1097 BailoutReason dont_optimize_reason() { return kNoReason; } 1098 int* ast_properties() { 1099 static int dummy = 42; 1100 return &dummy; 1101 } 1102 }; 1103 1104 1105 class PreParser; 1106 1107 class PreParserTraits { 1108 public: 1109 struct Type { 1110 // TODO(marja): To be removed. The Traits object should contain all the data 1111 // it needs. 1112 typedef PreParser* Parser; 1113 1114 // Used by FunctionState and BlockState. 1115 typedef PreParserScope Scope; 1116 typedef PreParserScope ScopePtr; 1117 1118 // PreParser doesn't need to store generator variables. 1119 typedef void GeneratorVariable; 1120 // No interaction with Zones. 1121 typedef void Zone; 1122 1123 typedef int AstProperties; 1124 typedef Vector<PreParserIdentifier> ParameterIdentifierVector; 1125 1126 // Return types for traversing functions. 1127 typedef PreParserIdentifier Identifier; 1128 typedef PreParserExpression Expression; 1129 typedef PreParserExpression YieldExpression; 1130 typedef PreParserExpression FunctionLiteral; 1131 typedef PreParserExpression ClassLiteral; 1132 typedef PreParserExpression ObjectLiteralProperty; 1133 typedef PreParserExpression Literal; 1134 typedef PreParserExpressionList ExpressionList; 1135 typedef PreParserExpressionList PropertyList; 1136 typedef PreParserStatementList StatementList; 1137 1138 // For constructing objects returned by the traversing functions. 1139 typedef PreParserFactory Factory; 1140 }; 1141 1142 class Checkpoint; 1143 1144 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} 1145 1146 // Custom operations executed when FunctionStates are created and 1147 // destructed. (The PreParser doesn't need to do anything.) 1148 template <typename FunctionState> 1149 static void SetUpFunctionState(FunctionState* function_state) {} 1150 template <typename FunctionState> 1151 static void TearDownFunctionState(FunctionState* function_state) {} 1152 1153 // Helper functions for recursive descent. 1154 static bool IsEvalOrArguments(PreParserIdentifier identifier) { 1155 return identifier.IsEvalOrArguments(); 1156 } 1157 1158 static bool IsPrototype(PreParserIdentifier identifier) { 1159 return identifier.IsPrototype(); 1160 } 1161 1162 static bool IsConstructor(PreParserIdentifier identifier) { 1163 return identifier.IsConstructor(); 1164 } 1165 1166 // Returns true if the expression is of type "this.foo". 1167 static bool IsThisProperty(PreParserExpression expression) { 1168 return expression.IsThisProperty(); 1169 } 1170 1171 static bool IsIdentifier(PreParserExpression expression) { 1172 return expression.IsIdentifier(); 1173 } 1174 1175 static PreParserIdentifier AsIdentifier(PreParserExpression expression) { 1176 return expression.AsIdentifier(); 1177 } 1178 1179 static bool IsFutureStrictReserved(PreParserIdentifier identifier) { 1180 return identifier.IsYield() || identifier.IsFutureStrictReserved(); 1181 } 1182 1183 static bool IsBoilerplateProperty(PreParserExpression property) { 1184 // PreParser doesn't count boilerplate properties. 1185 return false; 1186 } 1187 1188 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) { 1189 return false; 1190 } 1191 1192 // Functions for encapsulating the differences between parsing and preparsing; 1193 // operations interleaved with the recursive descent. 1194 static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) { 1195 // PreParser should not use FuncNameInferrer. 1196 UNREACHABLE(); 1197 } 1198 static void PushPropertyName(FuncNameInferrer* fni, 1199 PreParserExpression expression) { 1200 // PreParser should not use FuncNameInferrer. 1201 UNREACHABLE(); 1202 } 1203 static void InferFunctionName(FuncNameInferrer* fni, 1204 PreParserExpression expression) { 1205 // PreParser should not use FuncNameInferrer. 1206 UNREACHABLE(); 1207 } 1208 1209 static void CheckFunctionLiteralInsideTopLevelObjectLiteral( 1210 PreParserScope* scope, PreParserExpression property, bool* has_function) { 1211 } 1212 1213 static void CheckAssigningFunctionLiteralToProperty( 1214 PreParserExpression left, PreParserExpression right) {} 1215 1216 // PreParser doesn't need to keep track of eval calls. 1217 static void CheckPossibleEvalCall(PreParserExpression expression, 1218 PreParserScope* scope) {} 1219 1220 static PreParserExpression MarkExpressionAsAssigned( 1221 PreParserExpression expression) { 1222 // TODO(marja): To be able to produce the same errors, the preparser needs 1223 // to start tracking which expressions are variables and which are assigned. 1224 return expression; 1225 } 1226 1227 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x, 1228 PreParserExpression y, 1229 Token::Value op, 1230 int pos, 1231 PreParserFactory* factory) { 1232 return false; 1233 } 1234 1235 PreParserExpression BuildUnaryExpression(PreParserExpression expression, 1236 Token::Value op, int pos, 1237 PreParserFactory* factory) { 1238 return PreParserExpression::Default(); 1239 } 1240 1241 PreParserExpression NewThrowReferenceError(const char* type, int pos) { 1242 return PreParserExpression::Default(); 1243 } 1244 PreParserExpression NewThrowSyntaxError( 1245 const char* type, Handle<Object> arg, int pos) { 1246 return PreParserExpression::Default(); 1247 } 1248 PreParserExpression NewThrowTypeError( 1249 const char* type, Handle<Object> arg, int pos) { 1250 return PreParserExpression::Default(); 1251 } 1252 PreParserScope NewScope(PreParserScope* outer_scope, ScopeType scope_type) { 1253 return PreParserScope(outer_scope, scope_type); 1254 } 1255 1256 // Reporting errors. 1257 void ReportMessageAt(Scanner::Location location, 1258 const char* message, 1259 const char* arg = NULL, 1260 bool is_reference_error = false); 1261 void ReportMessageAt(int start_pos, 1262 int end_pos, 1263 const char* message, 1264 const char* arg = NULL, 1265 bool is_reference_error = false); 1266 1267 // "null" return type creators. 1268 static PreParserIdentifier EmptyIdentifier() { 1269 return PreParserIdentifier::Default(); 1270 } 1271 static PreParserIdentifier EmptyIdentifierString() { 1272 return PreParserIdentifier::Default(); 1273 } 1274 static PreParserExpression EmptyExpression() { 1275 return PreParserExpression::Default(); 1276 } 1277 static PreParserExpression EmptyArrowParamList() { 1278 return PreParserExpression::EmptyArrowParamList(); 1279 } 1280 static PreParserExpression EmptyLiteral() { 1281 return PreParserExpression::Default(); 1282 } 1283 static PreParserExpression EmptyObjectLiteralProperty() { 1284 return PreParserExpression::Default(); 1285 } 1286 static PreParserExpression EmptyFunctionLiteral() { 1287 return PreParserExpression::Default(); 1288 } 1289 static PreParserExpressionList NullExpressionList() { 1290 return PreParserExpressionList(); 1291 } 1292 1293 // Odd-ball literal creators. 1294 static PreParserExpression GetLiteralTheHole(int position, 1295 PreParserFactory* factory) { 1296 return PreParserExpression::Default(); 1297 } 1298 1299 // Producing data during the recursive descent. 1300 PreParserIdentifier GetSymbol(Scanner* scanner); 1301 PreParserIdentifier GetNumberAsSymbol(Scanner* scanner); 1302 1303 static PreParserIdentifier GetNextSymbol(Scanner* scanner) { 1304 return PreParserIdentifier::Default(); 1305 } 1306 1307 static PreParserExpression ThisExpression(PreParserScope* scope, 1308 PreParserFactory* factory) { 1309 return PreParserExpression::This(); 1310 } 1311 1312 static PreParserExpression SuperReference(PreParserScope* scope, 1313 PreParserFactory* factory) { 1314 return PreParserExpression::Super(); 1315 } 1316 1317 static PreParserExpression ClassLiteral(PreParserIdentifier name, 1318 PreParserExpression extends, 1319 PreParserExpression constructor, 1320 PreParserExpressionList properties, 1321 int position, 1322 PreParserFactory* factory) { 1323 return PreParserExpression::Default(); 1324 } 1325 1326 static PreParserExpression ExpressionFromLiteral( 1327 Token::Value token, int pos, Scanner* scanner, 1328 PreParserFactory* factory) { 1329 return PreParserExpression::Default(); 1330 } 1331 1332 static PreParserExpression ExpressionFromIdentifier( 1333 PreParserIdentifier name, int pos, PreParserScope* scope, 1334 PreParserFactory* factory) { 1335 return PreParserExpression::FromIdentifier(name); 1336 } 1337 1338 PreParserExpression ExpressionFromString(int pos, 1339 Scanner* scanner, 1340 PreParserFactory* factory = NULL); 1341 1342 PreParserExpression GetIterator(PreParserExpression iterable, 1343 PreParserFactory* factory) { 1344 return PreParserExpression::Default(); 1345 } 1346 1347 static PreParserExpressionList NewExpressionList(int size, void* zone) { 1348 return PreParserExpressionList(); 1349 } 1350 1351 static PreParserStatementList NewStatementList(int size, void* zone) { 1352 return PreParserStatementList(); 1353 } 1354 1355 static PreParserExpressionList NewPropertyList(int size, void* zone) { 1356 return PreParserExpressionList(); 1357 } 1358 1359 V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name, 1360 int* materialized_literal_count, 1361 int* expected_property_count, bool* ok) { 1362 UNREACHABLE(); 1363 } 1364 1365 V8_INLINE PreParserStatementList 1366 ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, 1367 Variable* fvar, Token::Value fvar_init_op, 1368 bool is_generator, bool* ok); 1369 1370 // Utility functions 1371 int DeclareArrowParametersFromExpression(PreParserExpression expression, 1372 PreParserScope* scope, 1373 Scanner::Location* dupe_loc, 1374 bool* ok) { 1375 // TODO(aperez): Detect duplicated identifiers in paramlists. 1376 *ok = expression.IsValidArrowParamList(); 1377 return 0; 1378 } 1379 1380 static AstValueFactory* ast_value_factory() { return NULL; } 1381 1382 void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {} 1383 1384 // Temporary glue; these functions will move to ParserBase. 1385 PreParserExpression ParseV8Intrinsic(bool* ok); 1386 PreParserExpression ParseFunctionLiteral( 1387 PreParserIdentifier name, Scanner::Location function_name_location, 1388 bool name_is_strict_reserved, FunctionKind kind, 1389 int function_token_position, FunctionLiteral::FunctionType type, 1390 FunctionLiteral::ArityRestriction arity_restriction, bool* ok); 1391 1392 private: 1393 PreParser* pre_parser_; 1394 }; 1395 1396 1397 // Preparsing checks a JavaScript program and emits preparse-data that helps 1398 // a later parsing to be faster. 1399 // See preparse-data-format.h for the data format. 1400 1401 // The PreParser checks that the syntax follows the grammar for JavaScript, 1402 // and collects some information about the program along the way. 1403 // The grammar check is only performed in order to understand the program 1404 // sufficiently to deduce some information about it, that can be used 1405 // to speed up later parsing. Finding errors is not the goal of pre-parsing, 1406 // rather it is to speed up properly written and correct programs. 1407 // That means that contextual checks (like a label being declared where 1408 // it is used) are generally omitted. 1409 class PreParser : public ParserBase<PreParserTraits> { 1410 public: 1411 typedef PreParserIdentifier Identifier; 1412 typedef PreParserExpression Expression; 1413 typedef PreParserStatement Statement; 1414 1415 enum PreParseResult { 1416 kPreParseStackOverflow, 1417 kPreParseSuccess 1418 }; 1419 1420 PreParser(Scanner* scanner, ParserRecorder* log, uintptr_t stack_limit) 1421 : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, NULL, NULL, 1422 this) {} 1423 1424 // Pre-parse the program from the character stream; returns true on 1425 // success (even if parsing failed, the pre-parse data successfully 1426 // captured the syntax error), and false if a stack-overflow happened 1427 // during parsing. 1428 PreParseResult PreParseProgram() { 1429 PreParserScope scope(scope_, GLOBAL_SCOPE); 1430 FunctionState top_scope(&function_state_, &scope_, &scope); 1431 bool ok = true; 1432 int start_position = scanner()->peek_location().beg_pos; 1433 ParseSourceElements(Token::EOS, &ok); 1434 if (stack_overflow()) return kPreParseStackOverflow; 1435 if (!ok) { 1436 ReportUnexpectedToken(scanner()->current_token()); 1437 } else if (scope_->strict_mode() == STRICT) { 1438 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); 1439 } 1440 return kPreParseSuccess; 1441 } 1442 1443 // Parses a single function literal, from the opening parentheses before 1444 // parameters to the closing brace after the body. 1445 // Returns a FunctionEntry describing the body of the function in enough 1446 // detail that it can be lazily compiled. 1447 // The scanner is expected to have matched the "function" or "function*" 1448 // keyword and parameters, and have consumed the initial '{'. 1449 // At return, unless an error occurred, the scanner is positioned before the 1450 // the final '}'. 1451 PreParseResult PreParseLazyFunction(StrictMode strict_mode, 1452 bool is_generator, 1453 ParserRecorder* log); 1454 1455 private: 1456 friend class PreParserTraits; 1457 1458 // These types form an algebra over syntactic categories that is just 1459 // rich enough to let us recognize and propagate the constructs that 1460 // are either being counted in the preparser data, or is important 1461 // to throw the correct syntax error exceptions. 1462 1463 enum VariableDeclarationContext { 1464 kSourceElement, 1465 kStatement, 1466 kForStatement 1467 }; 1468 1469 // If a list of variable declarations includes any initializers. 1470 enum VariableDeclarationProperties { 1471 kHasInitializers, 1472 kHasNoInitializers 1473 }; 1474 1475 1476 enum SourceElements { 1477 kUnknownSourceElements 1478 }; 1479 1480 // All ParseXXX functions take as the last argument an *ok parameter 1481 // which is set to false if parsing failed; it is unchanged otherwise. 1482 // By making the 'exception handling' explicit, we are forced to check 1483 // for failure at the call sites. 1484 Statement ParseSourceElement(bool* ok); 1485 SourceElements ParseSourceElements(int end_token, bool* ok); 1486 Statement ParseStatement(bool* ok); 1487 Statement ParseFunctionDeclaration(bool* ok); 1488 Statement ParseClassDeclaration(bool* ok); 1489 Statement ParseBlock(bool* ok); 1490 Statement ParseVariableStatement(VariableDeclarationContext var_context, 1491 bool* ok); 1492 Statement ParseVariableDeclarations(VariableDeclarationContext var_context, 1493 VariableDeclarationProperties* decl_props, 1494 int* num_decl, 1495 bool* ok); 1496 Statement ParseExpressionOrLabelledStatement(bool* ok); 1497 Statement ParseIfStatement(bool* ok); 1498 Statement ParseContinueStatement(bool* ok); 1499 Statement ParseBreakStatement(bool* ok); 1500 Statement ParseReturnStatement(bool* ok); 1501 Statement ParseWithStatement(bool* ok); 1502 Statement ParseSwitchStatement(bool* ok); 1503 Statement ParseDoWhileStatement(bool* ok); 1504 Statement ParseWhileStatement(bool* ok); 1505 Statement ParseForStatement(bool* ok); 1506 Statement ParseThrowStatement(bool* ok); 1507 Statement ParseTryStatement(bool* ok); 1508 Statement ParseDebuggerStatement(bool* ok); 1509 Expression ParseConditionalExpression(bool accept_IN, bool* ok); 1510 Expression ParseObjectLiteral(bool* ok); 1511 Expression ParseV8Intrinsic(bool* ok); 1512 1513 V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name, 1514 int* materialized_literal_count, 1515 int* expected_property_count, bool* ok); 1516 V8_INLINE PreParserStatementList 1517 ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, 1518 Variable* fvar, Token::Value fvar_init_op, 1519 bool is_generator, bool* ok); 1520 1521 Expression ParseFunctionLiteral( 1522 Identifier name, Scanner::Location function_name_location, 1523 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, 1524 FunctionLiteral::FunctionType function_type, 1525 FunctionLiteral::ArityRestriction arity_restriction, bool* ok); 1526 void ParseLazyFunctionLiteralBody(bool* ok); 1527 1528 bool CheckInOrOf(bool accept_OF); 1529 }; 1530 1531 1532 PreParserStatementList PreParser::ParseEagerFunctionBody( 1533 PreParserIdentifier function_name, int pos, Variable* fvar, 1534 Token::Value fvar_init_op, bool is_generator, bool* ok) { 1535 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 1536 1537 ParseSourceElements(Token::RBRACE, ok); 1538 if (!*ok) return PreParserStatementList(); 1539 1540 Expect(Token::RBRACE, ok); 1541 return PreParserStatementList(); 1542 } 1543 1544 1545 PreParserStatementList PreParserTraits::ParseEagerFunctionBody( 1546 PreParserIdentifier function_name, int pos, Variable* fvar, 1547 Token::Value fvar_init_op, bool is_generator, bool* ok) { 1548 return pre_parser_->ParseEagerFunctionBody(function_name, pos, fvar, 1549 fvar_init_op, is_generator, ok); 1550 } 1551 1552 1553 template <class Traits> 1554 ParserBase<Traits>::FunctionState::FunctionState( 1555 FunctionState** function_state_stack, 1556 typename Traits::Type::Scope** scope_stack, 1557 typename Traits::Type::Scope* scope, typename Traits::Type::Zone* zone, 1558 AstValueFactory* ast_value_factory, AstNode::IdGen* ast_node_id_gen) 1559 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize), 1560 next_handler_index_(0), 1561 expected_property_count_(0), 1562 is_generator_(false), 1563 generator_object_variable_(NULL), 1564 function_state_stack_(function_state_stack), 1565 outer_function_state_(*function_state_stack), 1566 scope_stack_(scope_stack), 1567 outer_scope_(*scope_stack), 1568 ast_node_id_gen_(ast_node_id_gen), 1569 factory_(zone, ast_value_factory, ast_node_id_gen) { 1570 *scope_stack_ = scope; 1571 *function_state_stack = this; 1572 Traits::SetUpFunctionState(this); 1573 } 1574 1575 1576 template <class Traits> 1577 ParserBase<Traits>::FunctionState::FunctionState( 1578 FunctionState** function_state_stack, 1579 typename Traits::Type::Scope** scope_stack, 1580 typename Traits::Type::Scope** scope, typename Traits::Type::Zone* zone, 1581 AstValueFactory* ast_value_factory, AstNode::IdGen* ast_node_id_gen) 1582 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize), 1583 next_handler_index_(0), 1584 expected_property_count_(0), 1585 is_generator_(false), 1586 generator_object_variable_(NULL), 1587 function_state_stack_(function_state_stack), 1588 outer_function_state_(*function_state_stack), 1589 scope_stack_(scope_stack), 1590 outer_scope_(*scope_stack), 1591 ast_node_id_gen_(ast_node_id_gen), 1592 factory_(zone, ast_value_factory, ast_node_id_gen) { 1593 *scope_stack_ = *scope; 1594 *function_state_stack = this; 1595 Traits::SetUpFunctionState(this); 1596 } 1597 1598 1599 template <class Traits> 1600 ParserBase<Traits>::FunctionState::~FunctionState() { 1601 *scope_stack_ = outer_scope_; 1602 *function_state_stack_ = outer_function_state_; 1603 Traits::TearDownFunctionState(this); 1604 } 1605 1606 1607 template<class Traits> 1608 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { 1609 Scanner::Location source_location = scanner()->location(); 1610 1611 // Four of the tokens are treated specially 1612 switch (token) { 1613 case Token::EOS: 1614 return ReportMessageAt(source_location, "unexpected_eos"); 1615 case Token::NUMBER: 1616 return ReportMessageAt(source_location, "unexpected_token_number"); 1617 case Token::STRING: 1618 return ReportMessageAt(source_location, "unexpected_token_string"); 1619 case Token::IDENTIFIER: 1620 return ReportMessageAt(source_location, "unexpected_token_identifier"); 1621 case Token::FUTURE_RESERVED_WORD: 1622 return ReportMessageAt(source_location, "unexpected_reserved"); 1623 case Token::LET: 1624 case Token::YIELD: 1625 case Token::FUTURE_STRICT_RESERVED_WORD: 1626 return ReportMessageAt(source_location, strict_mode() == SLOPPY 1627 ? "unexpected_token_identifier" : "unexpected_strict_reserved"); 1628 default: 1629 const char* name = Token::String(token); 1630 DCHECK(name != NULL); 1631 Traits::ReportMessageAt(source_location, "unexpected_token", name); 1632 } 1633 } 1634 1635 1636 template<class Traits> 1637 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( 1638 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, 1639 bool* ok) { 1640 Token::Value next = Next(); 1641 if (next == Token::IDENTIFIER) { 1642 IdentifierT name = this->GetSymbol(scanner()); 1643 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && 1644 strict_mode() == STRICT && this->IsEvalOrArguments(name)) { 1645 ReportMessage("strict_eval_arguments"); 1646 *ok = false; 1647 } 1648 return name; 1649 } else if (strict_mode() == SLOPPY && 1650 (next == Token::FUTURE_STRICT_RESERVED_WORD || 1651 (next == Token::LET) || 1652 (next == Token::YIELD && !is_generator()))) { 1653 return this->GetSymbol(scanner()); 1654 } else { 1655 this->ReportUnexpectedToken(next); 1656 *ok = false; 1657 return Traits::EmptyIdentifier(); 1658 } 1659 } 1660 1661 1662 template <class Traits> 1663 typename ParserBase<Traits>::IdentifierT ParserBase< 1664 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, 1665 bool* ok) { 1666 Token::Value next = Next(); 1667 if (next == Token::IDENTIFIER) { 1668 *is_strict_reserved = false; 1669 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || 1670 next == Token::LET || 1671 (next == Token::YIELD && !this->is_generator())) { 1672 *is_strict_reserved = true; 1673 } else { 1674 ReportUnexpectedToken(next); 1675 *ok = false; 1676 return Traits::EmptyIdentifier(); 1677 } 1678 return this->GetSymbol(scanner()); 1679 } 1680 1681 1682 template <class Traits> 1683 typename ParserBase<Traits>::IdentifierT 1684 ParserBase<Traits>::ParseIdentifierName(bool* ok) { 1685 Token::Value next = Next(); 1686 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && 1687 next != Token::LET && next != Token::YIELD && 1688 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { 1689 this->ReportUnexpectedToken(next); 1690 *ok = false; 1691 return Traits::EmptyIdentifier(); 1692 } 1693 return this->GetSymbol(scanner()); 1694 } 1695 1696 1697 template <class Traits> 1698 typename ParserBase<Traits>::IdentifierT 1699 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, 1700 bool* is_set, 1701 bool* ok) { 1702 IdentifierT result = ParseIdentifierName(ok); 1703 if (!*ok) return Traits::EmptyIdentifier(); 1704 scanner()->IsGetOrSet(is_get, is_set); 1705 return result; 1706 } 1707 1708 1709 template <class Traits> 1710 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral( 1711 bool seen_equal, bool* ok) { 1712 int pos = peek_position(); 1713 if (!scanner()->ScanRegExpPattern(seen_equal)) { 1714 Next(); 1715 ReportMessage("unterminated_regexp"); 1716 *ok = false; 1717 return Traits::EmptyExpression(); 1718 } 1719 1720 int literal_index = function_state_->NextMaterializedLiteralIndex(); 1721 1722 IdentifierT js_pattern = this->GetNextSymbol(scanner()); 1723 if (!scanner()->ScanRegExpFlags()) { 1724 Next(); 1725 ReportMessage("invalid_regexp_flags"); 1726 *ok = false; 1727 return Traits::EmptyExpression(); 1728 } 1729 IdentifierT js_flags = this->GetNextSymbol(scanner()); 1730 Next(); 1731 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); 1732 } 1733 1734 1735 #define CHECK_OK ok); \ 1736 if (!*ok) return this->EmptyExpression(); \ 1737 ((void)0 1738 #define DUMMY ) // to make indentation work 1739 #undef DUMMY 1740 1741 // Used in functions where the return type is not ExpressionT. 1742 #define CHECK_OK_CUSTOM(x) ok); \ 1743 if (!*ok) return this->x(); \ 1744 ((void)0 1745 #define DUMMY ) // to make indentation work 1746 #undef DUMMY 1747 1748 template <class Traits> 1749 typename ParserBase<Traits>::ExpressionT 1750 ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { 1751 // PrimaryExpression :: 1752 // 'this' 1753 // 'null' 1754 // 'true' 1755 // 'false' 1756 // Identifier 1757 // Number 1758 // String 1759 // ArrayLiteral 1760 // ObjectLiteral 1761 // RegExpLiteral 1762 // ClassLiteral 1763 // '(' Expression ')' 1764 1765 int pos = peek_position(); 1766 ExpressionT result = this->EmptyExpression(); 1767 Token::Value token = peek(); 1768 switch (token) { 1769 case Token::THIS: { 1770 Consume(Token::THIS); 1771 result = this->ThisExpression(scope_, factory()); 1772 break; 1773 } 1774 1775 case Token::NULL_LITERAL: 1776 case Token::TRUE_LITERAL: 1777 case Token::FALSE_LITERAL: 1778 case Token::NUMBER: 1779 Next(); 1780 result = this->ExpressionFromLiteral(token, pos, scanner(), factory()); 1781 break; 1782 1783 case Token::IDENTIFIER: 1784 case Token::LET: 1785 case Token::YIELD: 1786 case Token::FUTURE_STRICT_RESERVED_WORD: { 1787 // Using eval or arguments in this context is OK even in strict mode. 1788 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); 1789 result = this->ExpressionFromIdentifier(name, pos, scope_, factory()); 1790 break; 1791 } 1792 1793 case Token::STRING: { 1794 Consume(Token::STRING); 1795 result = this->ExpressionFromString(pos, scanner(), factory()); 1796 break; 1797 } 1798 1799 case Token::ASSIGN_DIV: 1800 result = this->ParseRegExpLiteral(true, CHECK_OK); 1801 break; 1802 1803 case Token::DIV: 1804 result = this->ParseRegExpLiteral(false, CHECK_OK); 1805 break; 1806 1807 case Token::LBRACK: 1808 result = this->ParseArrayLiteral(CHECK_OK); 1809 break; 1810 1811 case Token::LBRACE: 1812 result = this->ParseObjectLiteral(CHECK_OK); 1813 break; 1814 1815 case Token::LPAREN: 1816 Consume(Token::LPAREN); 1817 if (allow_arrow_functions() && peek() == Token::RPAREN) { 1818 // Arrow functions are the only expression type constructions 1819 // for which an empty parameter list "()" is valid input. 1820 Consume(Token::RPAREN); 1821 result = this->ParseArrowFunctionLiteral( 1822 pos, this->EmptyArrowParamList(), CHECK_OK); 1823 } else { 1824 // Heuristically try to detect immediately called functions before 1825 // seeing the call parentheses. 1826 parenthesized_function_ = (peek() == Token::FUNCTION); 1827 result = this->ParseExpression(true, CHECK_OK); 1828 result->increase_parenthesization_level(); 1829 Expect(Token::RPAREN, CHECK_OK); 1830 } 1831 break; 1832 1833 case Token::CLASS: { 1834 Consume(Token::CLASS); 1835 int class_token_position = position(); 1836 IdentifierT name = this->EmptyIdentifier(); 1837 bool is_strict_reserved_name = false; 1838 Scanner::Location class_name_location = Scanner::Location::invalid(); 1839 if (peek_any_identifier()) { 1840 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, 1841 CHECK_OK); 1842 class_name_location = scanner()->location(); 1843 } 1844 result = this->ParseClassLiteral(name, class_name_location, 1845 is_strict_reserved_name, 1846 class_token_position, CHECK_OK); 1847 break; 1848 } 1849 1850 case Token::MOD: 1851 if (allow_natives_syntax() || extension_ != NULL) { 1852 result = this->ParseV8Intrinsic(CHECK_OK); 1853 break; 1854 } 1855 // If we're not allowing special syntax we fall-through to the 1856 // default case. 1857 1858 default: { 1859 Next(); 1860 ReportUnexpectedToken(token); 1861 *ok = false; 1862 } 1863 } 1864 1865 return result; 1866 } 1867 1868 // Precedence = 1 1869 template <class Traits> 1870 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( 1871 bool accept_IN, bool* ok) { 1872 // Expression :: 1873 // AssignmentExpression 1874 // Expression ',' AssignmentExpression 1875 1876 ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK); 1877 while (peek() == Token::COMMA) { 1878 Expect(Token::COMMA, CHECK_OK); 1879 int pos = position(); 1880 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK); 1881 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); 1882 } 1883 return result; 1884 } 1885 1886 1887 template <class Traits> 1888 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( 1889 bool* ok) { 1890 // ArrayLiteral :: 1891 // '[' Expression? (',' Expression?)* ']' 1892 1893 int pos = peek_position(); 1894 typename Traits::Type::ExpressionList values = 1895 this->NewExpressionList(4, zone_); 1896 Expect(Token::LBRACK, CHECK_OK); 1897 while (peek() != Token::RBRACK) { 1898 ExpressionT elem = this->EmptyExpression(); 1899 if (peek() == Token::COMMA) { 1900 elem = this->GetLiteralTheHole(peek_position(), factory()); 1901 } else { 1902 elem = this->ParseAssignmentExpression(true, CHECK_OK); 1903 } 1904 values->Add(elem, zone_); 1905 if (peek() != Token::RBRACK) { 1906 Expect(Token::COMMA, CHECK_OK); 1907 } 1908 } 1909 Expect(Token::RBRACK, CHECK_OK); 1910 1911 // Update the scope information before the pre-parsing bailout. 1912 int literal_index = function_state_->NextMaterializedLiteralIndex(); 1913 1914 return factory()->NewArrayLiteral(values, literal_index, pos); 1915 } 1916 1917 1918 template <class Traits> 1919 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName( 1920 bool* is_get, bool* is_set, bool* is_static, bool* ok) { 1921 Token::Value next = peek(); 1922 switch (next) { 1923 case Token::STRING: 1924 Consume(Token::STRING); 1925 return this->GetSymbol(scanner_); 1926 case Token::NUMBER: 1927 Consume(Token::NUMBER); 1928 return this->GetNumberAsSymbol(scanner_); 1929 case Token::STATIC: 1930 *is_static = true; 1931 // Fall through. 1932 default: 1933 return ParseIdentifierNameOrGetOrSet(is_get, is_set, ok); 1934 } 1935 UNREACHABLE(); 1936 return this->EmptyIdentifier(); 1937 } 1938 1939 1940 template <class Traits> 1941 typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< 1942 Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, 1943 bool in_class, bool is_static, bool* ok) { 1944 ExpressionT value = this->EmptyExpression(); 1945 bool is_get = false; 1946 bool is_set = false; 1947 bool name_is_static = false; 1948 bool is_generator = allow_harmony_object_literals_ && Check(Token::MUL); 1949 1950 Token::Value name_token = peek(); 1951 int next_pos = peek_position(); 1952 IdentifierT name = 1953 ParsePropertyName(&is_get, &is_set, &name_is_static, 1954 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 1955 1956 if (fni_ != NULL) this->PushLiteralName(fni_, name); 1957 1958 if (!in_class && !is_generator && peek() == Token::COLON) { 1959 // PropertyDefinition : PropertyName ':' AssignmentExpression 1960 checker->CheckProperty(name_token, kValueProperty, 1961 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 1962 Consume(Token::COLON); 1963 value = this->ParseAssignmentExpression( 1964 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 1965 1966 } else if (is_generator || 1967 (allow_harmony_object_literals_ && peek() == Token::LPAREN)) { 1968 // Concise Method 1969 1970 if (is_static && this->IsPrototype(name)) { 1971 ReportMessageAt(scanner()->location(), "static_prototype"); 1972 *ok = false; 1973 return this->EmptyObjectLiteralProperty(); 1974 } 1975 if (is_generator && in_class && !is_static && this->IsConstructor(name)) { 1976 ReportMessageAt(scanner()->location(), "constructor_special_method"); 1977 *ok = false; 1978 return this->EmptyObjectLiteralProperty(); 1979 } 1980 1981 checker->CheckProperty(name_token, kValueProperty, 1982 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 1983 FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod 1984 : FunctionKind::kConciseMethod; 1985 1986 value = this->ParseFunctionLiteral( 1987 name, scanner()->location(), 1988 false, // reserved words are allowed here 1989 kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, 1990 FunctionLiteral::NORMAL_ARITY, 1991 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 1992 1993 } else if (in_class && name_is_static && !is_static) { 1994 // static MethodDefinition 1995 return ParsePropertyDefinition(checker, true, true, ok); 1996 1997 } else if (is_get || is_set) { 1998 // Accessor 1999 bool dont_care = false; 2000 name_token = peek(); 2001 name = ParsePropertyName(&dont_care, &dont_care, &dont_care, 2002 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2003 2004 // Validate the property. 2005 if (is_static && this->IsPrototype(name)) { 2006 ReportMessageAt(scanner()->location(), "static_prototype"); 2007 *ok = false; 2008 return this->EmptyObjectLiteralProperty(); 2009 } else if (in_class && !is_static && this->IsConstructor(name)) { 2010 // ES6, spec draft rev 27, treats static get constructor as an error too. 2011 // https://bugs.ecmascript.org/show_bug.cgi?id=3223 2012 // TODO(arv): Update when bug is resolved. 2013 ReportMessageAt(scanner()->location(), "constructor_special_method"); 2014 *ok = false; 2015 return this->EmptyObjectLiteralProperty(); 2016 } 2017 checker->CheckProperty(name_token, 2018 is_get ? kGetterProperty : kSetterProperty, 2019 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2020 2021 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( 2022 name, scanner()->location(), 2023 false, // reserved words are allowed here 2024 FunctionKind::kNormalFunction, RelocInfo::kNoPosition, 2025 FunctionLiteral::ANONYMOUS_EXPRESSION, 2026 is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY, 2027 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2028 return factory()->NewObjectLiteralProperty(is_get, value, next_pos, 2029 is_static); 2030 } else { 2031 Token::Value next = Next(); 2032 ReportUnexpectedToken(next); 2033 *ok = false; 2034 return this->EmptyObjectLiteralProperty(); 2035 } 2036 2037 uint32_t index; 2038 LiteralT key = this->IsArrayIndex(name, &index) 2039 ? factory()->NewNumberLiteral(index, next_pos) 2040 : factory()->NewStringLiteral(name, next_pos); 2041 2042 return factory()->NewObjectLiteralProperty(key, value, is_static); 2043 } 2044 2045 2046 template <class Traits> 2047 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( 2048 bool* ok) { 2049 // ObjectLiteral :: 2050 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' 2051 2052 int pos = peek_position(); 2053 typename Traits::Type::PropertyList properties = 2054 this->NewPropertyList(4, zone_); 2055 int number_of_boilerplate_properties = 0; 2056 bool has_function = false; 2057 2058 ObjectLiteralChecker checker(this, strict_mode()); 2059 2060 Expect(Token::LBRACE, CHECK_OK); 2061 2062 while (peek() != Token::RBRACE) { 2063 if (fni_ != NULL) fni_->Enter(); 2064 2065 const bool in_class = false; 2066 const bool is_static = false; 2067 ObjectLiteralPropertyT property = 2068 this->ParsePropertyDefinition(&checker, in_class, is_static, CHECK_OK); 2069 2070 // Mark top-level object literals that contain function literals and 2071 // pretenure the literal so it can be added as a constant function 2072 // property. (Parser only.) 2073 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property, 2074 &has_function); 2075 2076 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. 2077 if (this->IsBoilerplateProperty(property)) { 2078 number_of_boilerplate_properties++; 2079 } 2080 properties->Add(property, zone()); 2081 2082 if (peek() != Token::RBRACE) { 2083 // Need {} because of the CHECK_OK macro. 2084 Expect(Token::COMMA, CHECK_OK); 2085 } 2086 2087 if (fni_ != NULL) { 2088 fni_->Infer(); 2089 fni_->Leave(); 2090 } 2091 } 2092 Expect(Token::RBRACE, CHECK_OK); 2093 2094 // Computation of literal_index must happen before pre parse bailout. 2095 int literal_index = function_state_->NextMaterializedLiteralIndex(); 2096 2097 return factory()->NewObjectLiteral(properties, 2098 literal_index, 2099 number_of_boilerplate_properties, 2100 has_function, 2101 pos); 2102 } 2103 2104 2105 template <class Traits> 2106 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( 2107 bool* ok) { 2108 // Arguments :: 2109 // '(' (AssignmentExpression)*[','] ')' 2110 2111 typename Traits::Type::ExpressionList result = 2112 this->NewExpressionList(4, zone_); 2113 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); 2114 bool done = (peek() == Token::RPAREN); 2115 while (!done) { 2116 ExpressionT argument = this->ParseAssignmentExpression( 2117 true, CHECK_OK_CUSTOM(NullExpressionList)); 2118 result->Add(argument, zone_); 2119 if (result->length() > Code::kMaxArguments) { 2120 ReportMessage("too_many_arguments"); 2121 *ok = false; 2122 return this->NullExpressionList(); 2123 } 2124 done = (peek() == Token::RPAREN); 2125 if (!done) { 2126 // Need {} because of the CHECK_OK_CUSTOM macro. 2127 Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList)); 2128 } 2129 } 2130 Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList)); 2131 return result; 2132 } 2133 2134 // Precedence = 2 2135 template <class Traits> 2136 typename ParserBase<Traits>::ExpressionT 2137 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) { 2138 // AssignmentExpression :: 2139 // ConditionalExpression 2140 // ArrowFunction 2141 // YieldExpression 2142 // LeftHandSideExpression AssignmentOperator AssignmentExpression 2143 2144 Scanner::Location lhs_location = scanner()->peek_location(); 2145 2146 if (peek() == Token::YIELD && is_generator()) { 2147 return this->ParseYieldExpression(ok); 2148 } 2149 2150 if (fni_ != NULL) fni_->Enter(); 2151 typename Traits::Checkpoint checkpoint(this); 2152 ExpressionT expression = 2153 this->ParseConditionalExpression(accept_IN, CHECK_OK); 2154 2155 if (allow_arrow_functions() && peek() == Token::ARROW) { 2156 checkpoint.Restore(); 2157 expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos, 2158 expression, CHECK_OK); 2159 return expression; 2160 } 2161 2162 if (!Token::IsAssignmentOp(peek())) { 2163 if (fni_ != NULL) fni_->Leave(); 2164 // Parsed conditional expression only (no assignment). 2165 return expression; 2166 } 2167 2168 expression = this->CheckAndRewriteReferenceExpression( 2169 expression, lhs_location, "invalid_lhs_in_assignment", CHECK_OK); 2170 expression = this->MarkExpressionAsAssigned(expression); 2171 2172 Token::Value op = Next(); // Get assignment operator. 2173 int pos = position(); 2174 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK); 2175 2176 // TODO(1231235): We try to estimate the set of properties set by 2177 // constructors. We define a new property whenever there is an 2178 // assignment to a property of 'this'. We should probably only add 2179 // properties if we haven't seen them before. Otherwise we'll 2180 // probably overestimate the number of properties. 2181 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { 2182 function_state_->AddProperty(); 2183 } 2184 2185 this->CheckAssigningFunctionLiteralToProperty(expression, right); 2186 2187 if (fni_ != NULL) { 2188 // Check if the right hand side is a call to avoid inferring a 2189 // name if we're dealing with "a = function(){...}();"-like 2190 // expression. 2191 if ((op == Token::INIT_VAR 2192 || op == Token::INIT_CONST_LEGACY 2193 || op == Token::ASSIGN) 2194 && (!right->IsCall() && !right->IsCallNew())) { 2195 fni_->Infer(); 2196 } else { 2197 fni_->RemoveLastFunction(); 2198 } 2199 fni_->Leave(); 2200 } 2201 2202 return factory()->NewAssignment(op, expression, right, pos); 2203 } 2204 2205 template <class Traits> 2206 typename ParserBase<Traits>::ExpressionT 2207 ParserBase<Traits>::ParseYieldExpression(bool* ok) { 2208 // YieldExpression :: 2209 // 'yield' ([no line terminator] '*'? AssignmentExpression)? 2210 int pos = peek_position(); 2211 Expect(Token::YIELD, CHECK_OK); 2212 ExpressionT generator_object = 2213 factory()->NewVariableProxy(function_state_->generator_object_variable()); 2214 ExpressionT expression = Traits::EmptyExpression(); 2215 Yield::Kind kind = Yield::kSuspend; 2216 if (!scanner()->HasAnyLineTerminatorBeforeNext()) { 2217 if (Check(Token::MUL)) kind = Yield::kDelegating; 2218 switch (peek()) { 2219 case Token::EOS: 2220 case Token::SEMICOLON: 2221 case Token::RBRACE: 2222 case Token::RBRACK: 2223 case Token::RPAREN: 2224 case Token::COLON: 2225 case Token::COMMA: 2226 // The above set of tokens is the complete set of tokens that can appear 2227 // after an AssignmentExpression, and none of them can start an 2228 // AssignmentExpression. This allows us to avoid looking for an RHS for 2229 // a Yield::kSuspend operation, given only one look-ahead token. 2230 if (kind == Yield::kSuspend) 2231 break; 2232 DCHECK_EQ(Yield::kDelegating, kind); 2233 // Delegating yields require an RHS; fall through. 2234 default: 2235 expression = ParseAssignmentExpression(false, CHECK_OK); 2236 break; 2237 } 2238 } 2239 if (kind == Yield::kDelegating) { 2240 // var iterator = subject[Symbol.iterator](); 2241 expression = this->GetIterator(expression, factory()); 2242 } 2243 typename Traits::Type::YieldExpression yield = 2244 factory()->NewYield(generator_object, expression, kind, pos); 2245 if (kind == Yield::kDelegating) { 2246 yield->set_index(function_state_->NextHandlerIndex()); 2247 } 2248 return yield; 2249 } 2250 2251 2252 // Precedence = 3 2253 template <class Traits> 2254 typename ParserBase<Traits>::ExpressionT 2255 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) { 2256 // ConditionalExpression :: 2257 // LogicalOrExpression 2258 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression 2259 2260 int pos = peek_position(); 2261 // We start using the binary expression parser for prec >= 4 only! 2262 ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK); 2263 if (peek() != Token::CONDITIONAL) return expression; 2264 Consume(Token::CONDITIONAL); 2265 // In parsing the first assignment expression in conditional 2266 // expressions we always accept the 'in' keyword; see ECMA-262, 2267 // section 11.12, page 58. 2268 ExpressionT left = ParseAssignmentExpression(true, CHECK_OK); 2269 Expect(Token::COLON, CHECK_OK); 2270 ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK); 2271 return factory()->NewConditional(expression, left, right, pos); 2272 } 2273 2274 2275 // Precedence >= 4 2276 template <class Traits> 2277 typename ParserBase<Traits>::ExpressionT 2278 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { 2279 DCHECK(prec >= 4); 2280 ExpressionT x = this->ParseUnaryExpression(CHECK_OK); 2281 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { 2282 // prec1 >= 4 2283 while (Precedence(peek(), accept_IN) == prec1) { 2284 Token::Value op = Next(); 2285 int pos = position(); 2286 ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); 2287 2288 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos, 2289 factory())) { 2290 continue; 2291 } 2292 2293 // For now we distinguish between comparisons and other binary 2294 // operations. (We could combine the two and get rid of this 2295 // code and AST node eventually.) 2296 if (Token::IsCompareOp(op)) { 2297 // We have a comparison. 2298 Token::Value cmp = op; 2299 switch (op) { 2300 case Token::NE: cmp = Token::EQ; break; 2301 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; 2302 default: break; 2303 } 2304 x = factory()->NewCompareOperation(cmp, x, y, pos); 2305 if (cmp != op) { 2306 // The comparison was negated - add a NOT. 2307 x = factory()->NewUnaryOperation(Token::NOT, x, pos); 2308 } 2309 2310 } else { 2311 // We have a "normal" binary operation. 2312 x = factory()->NewBinaryOperation(op, x, y, pos); 2313 } 2314 } 2315 } 2316 return x; 2317 } 2318 2319 2320 template <class Traits> 2321 typename ParserBase<Traits>::ExpressionT 2322 ParserBase<Traits>::ParseUnaryExpression(bool* ok) { 2323 // UnaryExpression :: 2324 // PostfixExpression 2325 // 'delete' UnaryExpression 2326 // 'void' UnaryExpression 2327 // 'typeof' UnaryExpression 2328 // '++' UnaryExpression 2329 // '--' UnaryExpression 2330 // '+' UnaryExpression 2331 // '-' UnaryExpression 2332 // '~' UnaryExpression 2333 // '!' UnaryExpression 2334 2335 Token::Value op = peek(); 2336 if (Token::IsUnaryOp(op)) { 2337 op = Next(); 2338 int pos = position(); 2339 ExpressionT expression = ParseUnaryExpression(CHECK_OK); 2340 2341 // "delete identifier" is a syntax error in strict mode. 2342 if (op == Token::DELETE && strict_mode() == STRICT && 2343 this->IsIdentifier(expression)) { 2344 ReportMessage("strict_delete"); 2345 *ok = false; 2346 return this->EmptyExpression(); 2347 } 2348 2349 // Allow Traits do rewrite the expression. 2350 return this->BuildUnaryExpression(expression, op, pos, factory()); 2351 } else if (Token::IsCountOp(op)) { 2352 op = Next(); 2353 Scanner::Location lhs_location = scanner()->peek_location(); 2354 ExpressionT expression = this->ParseUnaryExpression(CHECK_OK); 2355 expression = this->CheckAndRewriteReferenceExpression( 2356 expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK); 2357 this->MarkExpressionAsAssigned(expression); 2358 2359 return factory()->NewCountOperation(op, 2360 true /* prefix */, 2361 expression, 2362 position()); 2363 2364 } else { 2365 return this->ParsePostfixExpression(ok); 2366 } 2367 } 2368 2369 2370 template <class Traits> 2371 typename ParserBase<Traits>::ExpressionT 2372 ParserBase<Traits>::ParsePostfixExpression(bool* ok) { 2373 // PostfixExpression :: 2374 // LeftHandSideExpression ('++' | '--')? 2375 2376 Scanner::Location lhs_location = scanner()->peek_location(); 2377 ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK); 2378 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 2379 Token::IsCountOp(peek())) { 2380 expression = this->CheckAndRewriteReferenceExpression( 2381 expression, lhs_location, "invalid_lhs_in_postfix_op", CHECK_OK); 2382 expression = this->MarkExpressionAsAssigned(expression); 2383 2384 Token::Value next = Next(); 2385 expression = 2386 factory()->NewCountOperation(next, 2387 false /* postfix */, 2388 expression, 2389 position()); 2390 } 2391 return expression; 2392 } 2393 2394 2395 template <class Traits> 2396 typename ParserBase<Traits>::ExpressionT 2397 ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) { 2398 // LeftHandSideExpression :: 2399 // (NewExpression | MemberExpression) ... 2400 2401 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); 2402 2403 while (true) { 2404 switch (peek()) { 2405 case Token::LBRACK: { 2406 Consume(Token::LBRACK); 2407 int pos = position(); 2408 ExpressionT index = ParseExpression(true, CHECK_OK); 2409 result = factory()->NewProperty(result, index, pos); 2410 Expect(Token::RBRACK, CHECK_OK); 2411 break; 2412 } 2413 2414 case Token::LPAREN: { 2415 int pos; 2416 if (scanner()->current_token() == Token::IDENTIFIER) { 2417 // For call of an identifier we want to report position of 2418 // the identifier as position of the call in the stack trace. 2419 pos = position(); 2420 } else { 2421 // For other kinds of calls we record position of the parenthesis as 2422 // position of the call. Note that this is extremely important for 2423 // expressions of the form function(){...}() for which call position 2424 // should not point to the closing brace otherwise it will intersect 2425 // with positions recorded for function literal and confuse debugger. 2426 pos = peek_position(); 2427 // Also the trailing parenthesis are a hint that the function will 2428 // be called immediately. If we happen to have parsed a preceding 2429 // function literal eagerly, we can also compile it eagerly. 2430 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { 2431 result->AsFunctionLiteral()->set_parenthesized(); 2432 } 2433 } 2434 typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK); 2435 2436 // Keep track of eval() calls since they disable all local variable 2437 // optimizations. 2438 // The calls that need special treatment are the 2439 // direct eval calls. These calls are all of the form eval(...), with 2440 // no explicit receiver. 2441 // These calls are marked as potentially direct eval calls. Whether 2442 // they are actually direct calls to eval is determined at run time. 2443 this->CheckPossibleEvalCall(result, scope_); 2444 result = factory()->NewCall(result, args, pos); 2445 if (fni_ != NULL) fni_->RemoveLastFunction(); 2446 break; 2447 } 2448 2449 case Token::PERIOD: { 2450 Consume(Token::PERIOD); 2451 int pos = position(); 2452 IdentifierT name = ParseIdentifierName(CHECK_OK); 2453 result = factory()->NewProperty( 2454 result, factory()->NewStringLiteral(name, pos), pos); 2455 if (fni_ != NULL) this->PushLiteralName(fni_, name); 2456 break; 2457 } 2458 2459 default: 2460 return result; 2461 } 2462 } 2463 } 2464 2465 2466 template <class Traits> 2467 typename ParserBase<Traits>::ExpressionT 2468 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) { 2469 // NewExpression :: 2470 // ('new')+ MemberExpression 2471 2472 // The grammar for new expressions is pretty warped. We can have several 'new' 2473 // keywords following each other, and then a MemberExpression. When we see '(' 2474 // after the MemberExpression, it's associated with the rightmost unassociated 2475 // 'new' to create a NewExpression with arguments. However, a NewExpression 2476 // can also occur without arguments. 2477 2478 // Examples of new expression: 2479 // new foo.bar().baz means (new (foo.bar)()).baz 2480 // new foo()() means (new foo())() 2481 // new new foo()() means (new (new foo())()) 2482 // new new foo means new (new foo) 2483 // new new foo() means new (new foo()) 2484 // new new foo().bar().baz means (new (new foo()).bar()).baz 2485 2486 if (peek() == Token::NEW) { 2487 Consume(Token::NEW); 2488 int new_pos = position(); 2489 ExpressionT result = this->EmptyExpression(); 2490 if (Check(Token::SUPER)) { 2491 result = this->SuperReference(scope_, factory()); 2492 } else { 2493 result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); 2494 } 2495 if (peek() == Token::LPAREN) { 2496 // NewExpression with arguments. 2497 typename Traits::Type::ExpressionList args = 2498 this->ParseArguments(CHECK_OK); 2499 result = factory()->NewCallNew(result, args, new_pos); 2500 // The expression can still continue with . or [ after the arguments. 2501 result = this->ParseMemberExpressionContinuation(result, CHECK_OK); 2502 return result; 2503 } 2504 // NewExpression without arguments. 2505 return factory()->NewCallNew(result, this->NewExpressionList(0, zone_), 2506 new_pos); 2507 } 2508 // No 'new' or 'super' keyword. 2509 return this->ParseMemberExpression(ok); 2510 } 2511 2512 2513 template <class Traits> 2514 typename ParserBase<Traits>::ExpressionT 2515 ParserBase<Traits>::ParseMemberExpression(bool* ok) { 2516 // MemberExpression :: 2517 // (PrimaryExpression | FunctionLiteral | ClassLiteral) 2518 // ('[' Expression ']' | '.' Identifier | Arguments)* 2519 2520 // The '[' Expression ']' and '.' Identifier parts are parsed by 2521 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the 2522 // caller. 2523 2524 // Parse the initial primary or function expression. 2525 ExpressionT result = this->EmptyExpression(); 2526 if (peek() == Token::FUNCTION) { 2527 Consume(Token::FUNCTION); 2528 int function_token_position = position(); 2529 bool is_generator = Check(Token::MUL); 2530 IdentifierT name = this->EmptyIdentifier(); 2531 bool is_strict_reserved_name = false; 2532 Scanner::Location function_name_location = Scanner::Location::invalid(); 2533 FunctionLiteral::FunctionType function_type = 2534 FunctionLiteral::ANONYMOUS_EXPRESSION; 2535 if (peek_any_identifier()) { 2536 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, 2537 CHECK_OK); 2538 function_name_location = scanner()->location(); 2539 function_type = FunctionLiteral::NAMED_EXPRESSION; 2540 } 2541 result = this->ParseFunctionLiteral( 2542 name, function_name_location, is_strict_reserved_name, 2543 is_generator ? FunctionKind::kGeneratorFunction 2544 : FunctionKind::kNormalFunction, 2545 function_token_position, function_type, FunctionLiteral::NORMAL_ARITY, 2546 CHECK_OK); 2547 } else if (peek() == Token::SUPER) { 2548 int beg_pos = position(); 2549 Consume(Token::SUPER); 2550 Token::Value next = peek(); 2551 if (next == Token::PERIOD || next == Token::LBRACK || 2552 next == Token::LPAREN) { 2553 result = this->SuperReference(scope_, factory()); 2554 } else { 2555 ReportMessageAt(Scanner::Location(beg_pos, position()), 2556 "unexpected_super"); 2557 *ok = false; 2558 return this->EmptyExpression(); 2559 } 2560 } else { 2561 result = ParsePrimaryExpression(CHECK_OK); 2562 } 2563 2564 result = ParseMemberExpressionContinuation(result, CHECK_OK); 2565 return result; 2566 } 2567 2568 2569 template <class Traits> 2570 typename ParserBase<Traits>::ExpressionT 2571 ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression, 2572 bool* ok) { 2573 // Parses this part of MemberExpression: 2574 // ('[' Expression ']' | '.' Identifier)* 2575 while (true) { 2576 switch (peek()) { 2577 case Token::LBRACK: { 2578 Consume(Token::LBRACK); 2579 int pos = position(); 2580 ExpressionT index = this->ParseExpression(true, CHECK_OK); 2581 expression = factory()->NewProperty(expression, index, pos); 2582 if (fni_ != NULL) { 2583 this->PushPropertyName(fni_, index); 2584 } 2585 Expect(Token::RBRACK, CHECK_OK); 2586 break; 2587 } 2588 case Token::PERIOD: { 2589 Consume(Token::PERIOD); 2590 int pos = position(); 2591 IdentifierT name = ParseIdentifierName(CHECK_OK); 2592 expression = factory()->NewProperty( 2593 expression, factory()->NewStringLiteral(name, pos), pos); 2594 if (fni_ != NULL) { 2595 this->PushLiteralName(fni_, name); 2596 } 2597 break; 2598 } 2599 default: 2600 return expression; 2601 } 2602 } 2603 DCHECK(false); 2604 return this->EmptyExpression(); 2605 } 2606 2607 2608 template <class Traits> 2609 typename ParserBase<Traits>::ExpressionT ParserBase< 2610 Traits>::ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, 2611 bool* ok) { 2612 // TODO(aperez): Change this to use ARROW_SCOPE 2613 typename Traits::Type::ScopePtr scope = 2614 this->NewScope(scope_, FUNCTION_SCOPE); 2615 typename Traits::Type::StatementList body; 2616 typename Traits::Type::AstProperties ast_properties; 2617 BailoutReason dont_optimize_reason = kNoReason; 2618 int num_parameters = -1; 2619 int materialized_literal_count = -1; 2620 int expected_property_count = -1; 2621 int handler_count = 0; 2622 2623 { 2624 FunctionState function_state(&function_state_, &scope_, &scope, zone(), 2625 this->ast_value_factory(), ast_node_id_gen_); 2626 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); 2627 num_parameters = Traits::DeclareArrowParametersFromExpression( 2628 params_ast, scope_, &dupe_error_loc, ok); 2629 if (!*ok) { 2630 ReportMessageAt( 2631 Scanner::Location(start_pos, scanner()->location().beg_pos), 2632 "malformed_arrow_function_parameter_list"); 2633 return this->EmptyExpression(); 2634 } 2635 2636 if (num_parameters > Code::kMaxArguments) { 2637 ReportMessageAt(Scanner::Location(params_ast->position(), position()), 2638 "too_many_parameters"); 2639 *ok = false; 2640 return this->EmptyExpression(); 2641 } 2642 2643 Expect(Token::ARROW, CHECK_OK); 2644 2645 if (peek() == Token::LBRACE) { 2646 // Multiple statemente body 2647 Consume(Token::LBRACE); 2648 bool is_lazily_parsed = 2649 (mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation()); 2650 if (is_lazily_parsed) { 2651 body = this->NewStatementList(0, zone()); 2652 this->SkipLazyFunctionBody(this->EmptyIdentifier(), 2653 &materialized_literal_count, 2654 &expected_property_count, CHECK_OK); 2655 } else { 2656 body = this->ParseEagerFunctionBody( 2657 this->EmptyIdentifier(), RelocInfo::kNoPosition, NULL, 2658 Token::INIT_VAR, false, // Not a generator. 2659 CHECK_OK); 2660 materialized_literal_count = 2661 function_state.materialized_literal_count(); 2662 expected_property_count = function_state.expected_property_count(); 2663 handler_count = function_state.handler_count(); 2664 } 2665 } else { 2666 // Single-expression body 2667 int pos = position(); 2668 parenthesized_function_ = false; 2669 ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK); 2670 body = this->NewStatementList(1, zone()); 2671 body->Add(factory()->NewReturnStatement(expression, pos), zone()); 2672 materialized_literal_count = function_state.materialized_literal_count(); 2673 expected_property_count = function_state.expected_property_count(); 2674 handler_count = function_state.handler_count(); 2675 } 2676 2677 scope->set_start_position(start_pos); 2678 scope->set_end_position(scanner()->location().end_pos); 2679 2680 // Arrow function *parameter lists* are always checked as in strict mode. 2681 bool function_name_is_strict_reserved = false; 2682 Scanner::Location function_name_loc = Scanner::Location::invalid(); 2683 Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); 2684 Scanner::Location reserved_loc = Scanner::Location::invalid(); 2685 this->CheckStrictFunctionNameAndParameters( 2686 this->EmptyIdentifier(), function_name_is_strict_reserved, 2687 function_name_loc, eval_args_error_loc, dupe_error_loc, reserved_loc, 2688 CHECK_OK); 2689 2690 // Validate strict mode. 2691 if (strict_mode() == STRICT) { 2692 CheckOctalLiteral(start_pos, scanner()->location().end_pos, CHECK_OK); 2693 } 2694 2695 if (allow_harmony_scoping() && strict_mode() == STRICT) 2696 this->CheckConflictingVarDeclarations(scope, CHECK_OK); 2697 2698 ast_properties = *factory()->visitor()->ast_properties(); 2699 dont_optimize_reason = factory()->visitor()->dont_optimize_reason(); 2700 } 2701 2702 FunctionLiteralT function_literal = factory()->NewFunctionLiteral( 2703 this->EmptyIdentifierString(), this->ast_value_factory(), scope, body, 2704 materialized_literal_count, expected_property_count, handler_count, 2705 num_parameters, FunctionLiteral::kNoDuplicateParameters, 2706 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction, 2707 FunctionLiteral::kNotParenthesized, FunctionKind::kArrowFunction, 2708 start_pos); 2709 2710 function_literal->set_function_token_position(start_pos); 2711 function_literal->set_ast_properties(&ast_properties); 2712 function_literal->set_dont_optimize_reason(dont_optimize_reason); 2713 2714 if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); 2715 2716 return function_literal; 2717 } 2718 2719 2720 template <class Traits> 2721 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseClassLiteral( 2722 IdentifierT name, Scanner::Location class_name_location, 2723 bool name_is_strict_reserved, int pos, bool* ok) { 2724 // All parts of a ClassDeclaration or a ClassExpression are strict code. 2725 if (name_is_strict_reserved) { 2726 ReportMessageAt(class_name_location, "unexpected_strict_reserved"); 2727 *ok = false; 2728 return this->EmptyExpression(); 2729 } 2730 if (this->IsEvalOrArguments(name)) { 2731 ReportMessageAt(class_name_location, "strict_eval_arguments"); 2732 *ok = false; 2733 return this->EmptyExpression(); 2734 } 2735 2736 // TODO(arv): Implement scopes and name binding in class body only. 2737 // TODO(arv): Maybe add CLASS_SCOPE? 2738 typename Traits::Type::ScopePtr extends_scope = 2739 this->NewScope(scope_, BLOCK_SCOPE); 2740 FunctionState extends_function_state( 2741 &function_state_, &scope_, &extends_scope, zone(), 2742 this->ast_value_factory(), ast_node_id_gen_); 2743 scope_->SetStrictMode(STRICT); 2744 scope_->SetScopeName(name); 2745 2746 ExpressionT extends = this->EmptyExpression(); 2747 if (Check(Token::EXTENDS)) { 2748 extends = this->ParseLeftHandSideExpression(CHECK_OK); 2749 } 2750 2751 ObjectLiteralChecker checker(this, STRICT); 2752 typename Traits::Type::PropertyList properties = 2753 this->NewPropertyList(4, zone_); 2754 FunctionLiteralT constructor = this->EmptyFunctionLiteral(); 2755 2756 Expect(Token::LBRACE, CHECK_OK); 2757 while (peek() != Token::RBRACE) { 2758 if (Check(Token::SEMICOLON)) continue; 2759 if (fni_ != NULL) fni_->Enter(); 2760 2761 const bool in_class = true; 2762 const bool is_static = false; 2763 ObjectLiteralPropertyT property = 2764 this->ParsePropertyDefinition(&checker, in_class, is_static, CHECK_OK); 2765 2766 properties->Add(property, zone()); 2767 2768 if (fni_ != NULL) { 2769 fni_->Infer(); 2770 fni_->Leave(); 2771 } 2772 } 2773 Expect(Token::RBRACE, CHECK_OK); 2774 2775 return this->ClassLiteral(name, extends, constructor, properties, pos, 2776 factory()); 2777 } 2778 2779 2780 template <typename Traits> 2781 typename ParserBase<Traits>::ExpressionT 2782 ParserBase<Traits>::CheckAndRewriteReferenceExpression( 2783 ExpressionT expression, 2784 Scanner::Location location, const char* message, bool* ok) { 2785 if (strict_mode() == STRICT && this->IsIdentifier(expression) && 2786 this->IsEvalOrArguments(this->AsIdentifier(expression))) { 2787 this->ReportMessageAt(location, "strict_eval_arguments", false); 2788 *ok = false; 2789 return this->EmptyExpression(); 2790 } else if (expression->IsValidReferenceExpression()) { 2791 return expression; 2792 } else if (expression->IsCall()) { 2793 // If it is a call, make it a runtime error for legacy web compatibility. 2794 // Rewrite `expr' to `expr[throw ReferenceError]'. 2795 int pos = location.beg_pos; 2796 ExpressionT error = this->NewThrowReferenceError(message, pos); 2797 return factory()->NewProperty(expression, error, pos); 2798 } else { 2799 this->ReportMessageAt(location, message, true); 2800 *ok = false; 2801 return this->EmptyExpression(); 2802 } 2803 } 2804 2805 2806 #undef CHECK_OK 2807 #undef CHECK_OK_CUSTOM 2808 2809 2810 template <typename Traits> 2811 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( 2812 Token::Value property, PropertyKind type, bool* ok) { 2813 int old; 2814 if (property == Token::NUMBER) { 2815 old = scanner()->FindNumber(&finder_, type); 2816 } else { 2817 old = scanner()->FindSymbol(&finder_, type); 2818 } 2819 PropertyKind old_type = static_cast<PropertyKind>(old); 2820 if (HasConflict(old_type, type)) { 2821 if (IsDataDataConflict(old_type, type)) { 2822 // Both are data properties. 2823 if (strict_mode_ == SLOPPY) return; 2824 parser()->ReportMessage("strict_duplicate_property"); 2825 } else if (IsDataAccessorConflict(old_type, type)) { 2826 // Both a data and an accessor property with the same name. 2827 parser()->ReportMessage("accessor_data_property"); 2828 } else { 2829 DCHECK(IsAccessorAccessorConflict(old_type, type)); 2830 // Both accessors of the same type. 2831 parser()->ReportMessage("accessor_get_set"); 2832 } 2833 *ok = false; 2834 } 2835 } 2836 } } // v8::internal 2837 2838 #endif // V8_PREPARSER_H 2839