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.
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"
20 // Common base class shared between parser and pre-parser. Traits encapsulate
21 // the differences between Parser and PreParser:
23 // - Return types: For example, Parser functions return Expression* and
24 // PreParser functions return PreParserExpression.
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
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.
38 // The traits are expected to contain the following typedefs:
40 // // In particular...
42 // // Used by FunctionState and BlockState.
44 // typedef GeneratorVariable;
45 // // Return types for traversing functions.
46 // typedef Identifier;
47 // typedef Expression;
48 // typedef FunctionLiteral;
49 // typedef ClassLiteral;
50 // typedef ObjectLiteralProperty;
52 // typedef ExpressionList;
53 // typedef PropertyList;
54 // // For constructing objects returned by the traversing functions.
60 template <typename Traits>
61 class ParserBase : public Traits {
63 // Shorten type names defined by Traits.
64 typedef typename Traits::Type::Expression ExpressionT;
65 typedef typename Traits::Type::Identifier IdentifierT;
66 typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
67 typedef typename Traits::Type::Literal LiteralT;
68 typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
70 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
71 v8::Extension* extension, AstValueFactory* ast_value_factory,
72 ParserRecorder* log, typename Traits::Type::Parser this_object)
73 : Traits(this_object),
74 parenthesized_function_(false),
76 function_state_(NULL),
77 extension_(extension),
79 ast_value_factory_(ast_value_factory),
81 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
82 stack_limit_(stack_limit),
85 stack_overflow_(false),
87 allow_natives_(false),
88 allow_harmony_arrow_functions_(false),
89 allow_harmony_object_literals_(false),
90 allow_harmony_sloppy_(false),
91 allow_harmony_computed_property_names_(false),
92 allow_harmony_rest_params_(false),
93 allow_strong_mode_(false) {}
95 // Getters that indicate whether certain syntactical constructs are
96 // allowed to be parsed by this instance of the parser.
97 bool allow_lazy() const { return allow_lazy_; }
98 bool allow_natives() const { return allow_natives_; }
99 bool allow_harmony_arrow_functions() const {
100 return allow_harmony_arrow_functions_;
102 bool allow_harmony_modules() const { return scanner()->HarmonyModules(); }
103 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
104 bool allow_harmony_numeric_literals() const {
105 return scanner()->HarmonyNumericLiterals();
107 bool allow_harmony_classes() const { return scanner()->HarmonyClasses(); }
108 bool allow_harmony_object_literals() const {
109 return allow_harmony_object_literals_;
111 bool allow_harmony_templates() const { return scanner()->HarmonyTemplates(); }
112 bool allow_harmony_sloppy() const { return allow_harmony_sloppy_; }
113 bool allow_harmony_unicode() const { return scanner()->HarmonyUnicode(); }
114 bool allow_harmony_computed_property_names() const {
115 return allow_harmony_computed_property_names_;
117 bool allow_harmony_rest_params() const {
118 return allow_harmony_rest_params_;
121 bool allow_strong_mode() const { return allow_strong_mode_; }
123 // Setters that determine whether certain syntactical constructs are
124 // allowed to be parsed by this instance of the parser.
125 void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
126 void set_allow_natives(bool allow) { allow_natives_ = allow; }
127 void set_allow_harmony_arrow_functions(bool allow) {
128 allow_harmony_arrow_functions_ = allow;
130 void set_allow_harmony_modules(bool allow) {
131 scanner()->SetHarmonyModules(allow);
133 void set_allow_harmony_scoping(bool allow) {
134 scanner()->SetHarmonyScoping(allow);
136 void set_allow_harmony_numeric_literals(bool allow) {
137 scanner()->SetHarmonyNumericLiterals(allow);
139 void set_allow_harmony_classes(bool allow) {
140 scanner()->SetHarmonyClasses(allow);
142 void set_allow_harmony_object_literals(bool allow) {
143 allow_harmony_object_literals_ = allow;
145 void set_allow_harmony_templates(bool allow) {
146 scanner()->SetHarmonyTemplates(allow);
148 void set_allow_harmony_sloppy(bool allow) {
149 allow_harmony_sloppy_ = allow;
151 void set_allow_harmony_unicode(bool allow) {
152 scanner()->SetHarmonyUnicode(allow);
154 void set_allow_harmony_computed_property_names(bool allow) {
155 allow_harmony_computed_property_names_ = allow;
157 void set_allow_harmony_rest_params(bool allow) {
158 allow_harmony_rest_params_ = allow;
160 void set_allow_strong_mode(bool allow) { allow_strong_mode_ = allow; }
163 enum AllowEvalOrArgumentsAsIdentifier {
164 kAllowEvalOrArguments,
165 kDontAllowEvalOrArguments
173 enum VariableDeclarationContext {
179 // If a list of variable declarations includes any initializers.
180 enum VariableDeclarationProperties { kHasInitializers, kHasNoInitializers };
183 class ObjectLiteralCheckerBase;
185 // ---------------------------------------------------------------------------
186 // FunctionState and BlockState together implement the parser's scope stack.
187 // The parser's current scope is in scope_. BlockState and FunctionState
188 // constructors push on the scope stack and the destructors pop. They are also
189 // used to hold the parser's per-function and per-block state.
190 class BlockState BASE_EMBEDDED {
192 BlockState(Scope** scope_stack, Scope* scope)
193 : scope_stack_(scope_stack), outer_scope_(*scope_stack), scope_(scope) {
194 *scope_stack_ = scope_;
196 ~BlockState() { *scope_stack_ = outer_scope_; }
199 Scope** scope_stack_;
204 class FunctionState BASE_EMBEDDED {
206 FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
207 Scope* scope, FunctionKind kind,
208 typename Traits::Type::Factory* factory);
211 int NextMaterializedLiteralIndex() {
212 return next_materialized_literal_index_++;
214 int materialized_literal_count() {
215 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
218 int NextHandlerIndex() { return next_handler_index_++; }
219 int handler_count() { return next_handler_index_; }
221 void AddProperty() { expected_property_count_++; }
222 int expected_property_count() { return expected_property_count_; }
224 bool is_generator() const { return IsGeneratorFunction(kind_); }
226 FunctionKind kind() const { return kind_; }
227 FunctionState* outer() const { return outer_function_state_; }
229 void set_generator_object_variable(
230 typename Traits::Type::GeneratorVariable* variable) {
231 DCHECK(variable != NULL);
232 DCHECK(is_generator());
233 generator_object_variable_ = variable;
235 typename Traits::Type::GeneratorVariable* generator_object_variable()
237 return generator_object_variable_;
240 typename Traits::Type::Factory* factory() { return factory_; }
243 // Used to assign an index to each literal that needs materialization in
244 // the function. Includes regexp literals, and boilerplate for object and
246 int next_materialized_literal_index_;
248 // Used to assign a per-function index to try and catch handlers.
249 int next_handler_index_;
251 // Properties count estimation.
252 int expected_property_count_;
255 // For generators, this variable may hold the generator object. It variable
256 // is used by yield expressions and return statements. It is not necessary
257 // for generator functions to have this variable set.
258 Variable* generator_object_variable_;
260 FunctionState** function_state_stack_;
261 FunctionState* outer_function_state_;
262 Scope** scope_stack_;
264 typename Traits::Type::Factory* factory_;
266 friend class ParserTraits;
267 friend class Checkpoint;
270 // Annoyingly, arrow functions first parse as comma expressions, then when we
271 // see the => we have to go back and reinterpret the arguments as being formal
272 // parameters. To do so we need to reset some of the parser state back to
273 // what it was before the arguments were first seen.
274 class Checkpoint BASE_EMBEDDED {
276 explicit Checkpoint(ParserBase* parser) {
277 function_state_ = parser->function_state_;
278 next_materialized_literal_index_ =
279 function_state_->next_materialized_literal_index_;
280 next_handler_index_ = function_state_->next_handler_index_;
281 expected_property_count_ = function_state_->expected_property_count_;
285 function_state_->next_materialized_literal_index_ =
286 next_materialized_literal_index_;
287 function_state_->next_handler_index_ = next_handler_index_;
288 function_state_->expected_property_count_ = expected_property_count_;
292 FunctionState* function_state_;
293 int next_materialized_literal_index_;
294 int next_handler_index_;
295 int expected_property_count_;
298 class ParsingModeScope BASE_EMBEDDED {
300 ParsingModeScope(ParserBase* parser, Mode mode)
302 old_mode_(parser->mode()) {
303 parser_->mode_ = mode;
305 ~ParsingModeScope() {
306 parser_->mode_ = old_mode_;
314 Scope* NewScope(Scope* parent, ScopeType scope_type,
315 FunctionKind kind = kNormalFunction) {
316 DCHECK(ast_value_factory());
317 DCHECK(scope_type != MODULE_SCOPE || allow_harmony_modules());
318 DCHECK((scope_type == FUNCTION_SCOPE && IsValidFunctionKind(kind)) ||
319 kind == kNormalFunction);
321 new (zone()) Scope(zone(), parent, scope_type, ast_value_factory());
322 bool uninitialized_this = IsSubclassConstructor(kind);
323 result->Initialize(uninitialized_this);
327 Scanner* scanner() const { return scanner_; }
328 AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
329 int position() { return scanner_->location().beg_pos; }
330 int peek_position() { return scanner_->peek_location().beg_pos; }
331 bool stack_overflow() const { return stack_overflow_; }
332 void set_stack_overflow() { stack_overflow_ = true; }
333 Mode mode() const { return mode_; }
334 Zone* zone() const { return zone_; }
336 INLINE(Token::Value peek()) {
337 if (stack_overflow_) return Token::ILLEGAL;
338 return scanner()->peek();
341 INLINE(Token::Value Next()) {
342 if (stack_overflow_) return Token::ILLEGAL;
344 if (GetCurrentStackPosition() < stack_limit_) {
345 // Any further calls to Next or peek will return the illegal token.
346 // The current call must return the next token, which might already
347 // have been peek'ed.
348 stack_overflow_ = true;
351 return scanner()->Next();
354 void Consume(Token::Value token) {
355 Token::Value next = Next();
358 DCHECK(next == token);
361 bool Check(Token::Value token) {
362 Token::Value next = peek();
370 void Expect(Token::Value token, bool* ok) {
371 Token::Value next = Next();
373 ReportUnexpectedToken(next);
378 void ExpectSemicolon(bool* ok) {
379 // Check for automatic semicolon insertion according to
380 // the rules given in ECMA-262, section 7.9, page 21.
381 Token::Value tok = peek();
382 if (tok == Token::SEMICOLON) {
386 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
387 tok == Token::RBRACE ||
391 Expect(Token::SEMICOLON, ok);
394 bool peek_any_identifier() {
395 Token::Value next = peek();
396 return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD ||
397 next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
398 next == Token::STATIC || next == Token::YIELD;
401 bool CheckContextualKeyword(Vector<const char> keyword) {
402 if (PeekContextualKeyword(keyword)) {
403 Consume(Token::IDENTIFIER);
409 bool PeekContextualKeyword(Vector<const char> keyword) {
410 return peek() == Token::IDENTIFIER &&
411 scanner()->is_next_contextual_keyword(keyword);
414 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
415 Expect(Token::IDENTIFIER, ok);
417 if (!scanner()->is_literal_contextual_keyword(keyword)) {
418 ReportUnexpectedToken(scanner()->current_token());
424 bool accept_OF, ForEachStatement::VisitMode* visit_mode, bool* ok) {
425 if (Check(Token::IN)) {
426 if (is_strong(language_mode())) {
427 ReportMessageAt(scanner()->location(), "strong_for_in");
430 *visit_mode = ForEachStatement::ENUMERATE;
433 } else if (accept_OF && CheckContextualKeyword(CStrVector("of"))) {
434 *visit_mode = ForEachStatement::ITERATE;
440 // Checks whether an octal literal was last seen between beg_pos and end_pos.
441 // If so, reports an error. Only called for strict mode and template strings.
442 void CheckOctalLiteral(int beg_pos, int end_pos, const char* error,
444 Scanner::Location octal = scanner()->octal_position();
445 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
446 octal.end_pos <= end_pos) {
447 ReportMessageAt(octal, error);
448 scanner()->clear_octal_position();
453 inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) {
454 CheckOctalLiteral(beg_pos, end_pos, "strict_octal_literal", ok);
457 inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) {
458 CheckOctalLiteral(beg_pos, end_pos, "template_octal_literal", ok);
461 // Checking the name of a function literal. This has to be done after parsing
462 // the function, since the function can declare itself strict.
463 void CheckFunctionName(LanguageMode language_mode, FunctionKind kind,
464 IdentifierT function_name,
465 bool function_name_is_strict_reserved,
466 const Scanner::Location& function_name_loc,
468 // Property names are never checked.
469 if (IsConciseMethod(kind) || IsAccessorFunction(kind)) return;
470 // The function name needs to be checked in strict mode.
471 if (is_sloppy(language_mode)) return;
473 if (this->IsEvalOrArguments(function_name)) {
474 Traits::ReportMessageAt(function_name_loc, "strict_eval_arguments");
478 if (function_name_is_strict_reserved) {
479 Traits::ReportMessageAt(function_name_loc, "unexpected_strict_reserved");
485 // Checking the parameter names of a function literal. This has to be done
486 // after parsing the function, since the function can declare itself strict.
487 void CheckFunctionParameterNames(LanguageMode language_mode,
489 const Scanner::Location& eval_args_error_loc,
490 const Scanner::Location& dupe_error_loc,
491 const Scanner::Location& reserved_loc,
493 if (is_sloppy(language_mode) && !strict_params) return;
495 if (is_strict(language_mode) && eval_args_error_loc.IsValid()) {
496 Traits::ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
500 // TODO(arv): When we add support for destructuring in setters we also need
501 // to check for duplicate names.
502 if (dupe_error_loc.IsValid()) {
503 Traits::ReportMessageAt(dupe_error_loc, "strict_param_dupe");
507 if (reserved_loc.IsValid()) {
508 Traits::ReportMessageAt(reserved_loc, "unexpected_strict_reserved");
514 // Determine precedence of given token.
515 static int Precedence(Token::Value token, bool accept_IN) {
516 if (token == Token::IN && !accept_IN)
517 return 0; // 0 precedence will terminate binary expression parsing
518 return Token::Precedence(token);
521 typename Traits::Type::Factory* factory() {
522 return function_state_->factory();
525 LanguageMode language_mode() { return scope_->language_mode(); }
526 bool is_generator() const { return function_state_->is_generator(); }
528 // Report syntax errors.
529 void ReportMessage(const char* message, const char* arg = NULL,
530 bool is_reference_error = false) {
531 Scanner::Location source_location = scanner()->location();
532 Traits::ReportMessageAt(source_location, message, arg, is_reference_error);
535 void ReportMessageAt(Scanner::Location location, const char* message,
536 bool is_reference_error = false) {
537 Traits::ReportMessageAt(location, message,
538 reinterpret_cast<const char*>(0),
542 void ReportUnexpectedToken(Token::Value token);
544 // Recursive descent functions:
546 // Parses an identifier that is valid for the current scope, in particular it
547 // fails on strict mode future reserved keywords in a strict scope. If
548 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
549 // "arguments" as identifier even in strict mode (this is needed in cases like
550 // "var foo = eval;").
551 IdentifierT ParseIdentifier(
552 AllowEvalOrArgumentsAsIdentifier,
554 // Parses an identifier or a strict mode future reserved word, and indicate
555 // whether it is strict mode future reserved.
556 IdentifierT ParseIdentifierOrStrictReservedWord(
557 bool* is_strict_reserved,
559 IdentifierT ParseIdentifierName(bool* ok);
560 // Parses an identifier and determines whether or not it is 'get' or 'set'.
561 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get,
565 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok);
567 ExpressionT ParsePrimaryExpression(bool* ok);
568 ExpressionT ParseExpression(bool accept_IN, bool* ok);
569 ExpressionT ParseArrayLiteral(bool* ok);
570 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set,
571 bool* is_static, bool* is_computed_name,
573 ExpressionT ParseObjectLiteral(bool* ok);
574 ObjectLiteralPropertyT ParsePropertyDefinition(
575 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
576 bool is_static, bool* is_computed_name, bool* has_seen_constructor,
578 typename Traits::Type::ExpressionList ParseArguments(bool* ok);
579 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
580 ExpressionT ParseYieldExpression(bool* ok);
581 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
582 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
583 ExpressionT ParseUnaryExpression(bool* ok);
584 ExpressionT ParsePostfixExpression(bool* ok);
585 ExpressionT ParseLeftHandSideExpression(bool* ok);
586 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
587 ExpressionT ParseMemberExpression(bool* ok);
588 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
590 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast,
592 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok);
593 void AddTemplateExpression(ExpressionT);
594 ExpressionT ParseSuperExpression(bool is_new, bool* ok);
596 // Checks if the expression is a valid reference expression (e.g., on the
597 // left-hand side of assignments). Although ruled out by ECMA as early errors,
598 // we allow calls for web compatibility and rewrite them to a runtime throw.
599 ExpressionT CheckAndRewriteReferenceExpression(
600 ExpressionT expression,
601 Scanner::Location location, const char* message, bool* ok);
603 // Used to validate property names in object literals and class literals
610 class ObjectLiteralCheckerBase {
612 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
614 virtual void CheckProperty(Token::Value property, PropertyKind type,
615 bool is_static, bool is_generator, bool* ok) = 0;
617 virtual ~ObjectLiteralCheckerBase() {}
620 ParserBase* parser() const { return parser_; }
621 Scanner* scanner() const { return parser_->scanner(); }
627 // Validation per ES6 object literals.
628 class ObjectLiteralChecker : public ObjectLiteralCheckerBase {
630 explicit ObjectLiteralChecker(ParserBase* parser)
631 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {}
633 void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
634 bool is_generator, bool* ok) OVERRIDE;
637 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); }
639 bool has_seen_proto_;
642 // Validation per ES6 class literals.
643 class ClassLiteralChecker : public ObjectLiteralCheckerBase {
645 explicit ClassLiteralChecker(ParserBase* parser)
646 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {}
648 void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
649 bool is_generator, bool* ok) OVERRIDE;
652 bool IsConstructor() {
653 return this->scanner()->LiteralMatches("constructor", 11);
656 return this->scanner()->LiteralMatches("prototype", 9);
659 bool has_seen_constructor_;
662 // If true, the next (and immediately following) function literal is
663 // preceded by a parenthesis.
664 // Heuristically that means that the function will be called immediately,
665 // so never lazily compile it.
666 bool parenthesized_function_;
668 Scope* scope_; // Scope stack.
669 FunctionState* function_state_; // Function state stack.
670 v8::Extension* extension_;
671 FuncNameInferrer* fni_;
672 AstValueFactory* ast_value_factory_; // Not owned.
673 ParserRecorder* log_;
675 uintptr_t stack_limit_;
681 bool stack_overflow_;
685 bool allow_harmony_arrow_functions_;
686 bool allow_harmony_object_literals_;
687 bool allow_harmony_sloppy_;
688 bool allow_harmony_computed_property_names_;
689 bool allow_harmony_rest_params_;
690 bool allow_strong_mode_;
694 class PreParserIdentifier {
696 PreParserIdentifier() : type_(kUnknownIdentifier) {}
697 static PreParserIdentifier Default() {
698 return PreParserIdentifier(kUnknownIdentifier);
700 static PreParserIdentifier Eval() {
701 return PreParserIdentifier(kEvalIdentifier);
703 static PreParserIdentifier Arguments() {
704 return PreParserIdentifier(kArgumentsIdentifier);
706 static PreParserIdentifier FutureReserved() {
707 return PreParserIdentifier(kFutureReservedIdentifier);
709 static PreParserIdentifier FutureStrictReserved() {
710 return PreParserIdentifier(kFutureStrictReservedIdentifier);
712 static PreParserIdentifier Let() {
713 return PreParserIdentifier(kLetIdentifier);
715 static PreParserIdentifier Static() {
716 return PreParserIdentifier(kStaticIdentifier);
718 static PreParserIdentifier Yield() {
719 return PreParserIdentifier(kYieldIdentifier);
721 static PreParserIdentifier Prototype() {
722 return PreParserIdentifier(kPrototypeIdentifier);
724 static PreParserIdentifier Constructor() {
725 return PreParserIdentifier(kConstructorIdentifier);
727 bool IsEval() const { return type_ == kEvalIdentifier; }
728 bool IsArguments() const { return type_ == kArgumentsIdentifier; }
729 bool IsEvalOrArguments() const { return IsEval() || IsArguments(); }
730 bool IsLet() const { return type_ == kLetIdentifier; }
731 bool IsStatic() const { return type_ == kStaticIdentifier; }
732 bool IsYield() const { return type_ == kYieldIdentifier; }
733 bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
734 bool IsConstructor() const { return type_ == kConstructorIdentifier; }
735 bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; }
736 bool IsFutureStrictReserved() const {
737 return type_ == kFutureStrictReservedIdentifier ||
738 type_ == kLetIdentifier || type_ == kStaticIdentifier ||
739 type_ == kYieldIdentifier;
741 bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; }
742 V8_INLINE bool IsValidArrowParam() const {
743 // A valid identifier can be an arrow function parameter
744 // except for eval, arguments, yield, and reserved keywords.
745 return !(IsEval() || IsArguments() || IsFutureStrictReserved());
748 // Allow identifier->name()[->length()] to work. The preparser
749 // does not need the actual positions/lengths of the identifiers.
750 const PreParserIdentifier* operator->() const { return this; }
751 const PreParserIdentifier raw_name() const { return *this; }
753 int position() const { return 0; }
754 int length() const { return 0; }
759 kFutureReservedIdentifier,
760 kFutureStrictReservedIdentifier,
765 kArgumentsIdentifier,
766 kPrototypeIdentifier,
767 kConstructorIdentifier
769 explicit PreParserIdentifier(Type type) : type_(type) {}
772 friend class PreParserExpression;
776 class PreParserExpression {
778 static PreParserExpression Default() {
779 return PreParserExpression(TypeField::encode(kExpression));
782 static PreParserExpression FromIdentifier(PreParserIdentifier id) {
783 return PreParserExpression(TypeField::encode(kIdentifierExpression) |
784 IdentifierTypeField::encode(id.type_));
787 static PreParserExpression BinaryOperation(PreParserExpression left,
789 PreParserExpression right) {
790 bool valid_arrow_param_list =
791 op == Token::COMMA && !left.is_parenthesized() &&
792 !right.is_parenthesized() && left.IsValidArrowParams() &&
793 right.IsValidArrowParams();
794 return PreParserExpression(
795 TypeField::encode(kBinaryOperationExpression) |
796 IsValidArrowParamListField::encode(valid_arrow_param_list));
799 static PreParserExpression EmptyArrowParamList() {
800 // Any expression for which IsValidArrowParamList() returns true
802 return FromIdentifier(PreParserIdentifier::Default());
805 static PreParserExpression StringLiteral() {
806 return PreParserExpression(TypeField::encode(kStringLiteralExpression));
809 static PreParserExpression UseStrictStringLiteral() {
810 return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
811 IsUseStrictField::encode(true));
814 static PreParserExpression UseStrongStringLiteral() {
815 return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
816 IsUseStrongField::encode(true));
819 static PreParserExpression This() {
820 return PreParserExpression(TypeField::encode(kExpression) |
821 ExpressionTypeField::encode(kThisExpression));
824 static PreParserExpression Super() {
825 return PreParserExpression(TypeField::encode(kExpression) |
826 ExpressionTypeField::encode(kSuperExpression));
829 static PreParserExpression ThisProperty() {
830 return PreParserExpression(
831 TypeField::encode(kExpression) |
832 ExpressionTypeField::encode(kThisPropertyExpression));
835 static PreParserExpression Property() {
836 return PreParserExpression(
837 TypeField::encode(kExpression) |
838 ExpressionTypeField::encode(kPropertyExpression));
841 static PreParserExpression Call() {
842 return PreParserExpression(TypeField::encode(kExpression) |
843 ExpressionTypeField::encode(kCallExpression));
846 static PreParserExpression NoTemplateTag() {
847 return PreParserExpression(TypeField::encode(kExpression) |
848 ExpressionTypeField::encode(
849 kNoTemplateTagExpression));
852 bool IsIdentifier() const {
853 return TypeField::decode(code_) == kIdentifierExpression;
856 PreParserIdentifier AsIdentifier() const {
857 DCHECK(IsIdentifier());
858 return PreParserIdentifier(IdentifierTypeField::decode(code_));
861 bool IsStringLiteral() const {
862 return TypeField::decode(code_) == kStringLiteralExpression;
865 bool IsUseStrictLiteral() const {
866 return TypeField::decode(code_) == kStringLiteralExpression &&
867 IsUseStrictField::decode(code_);
870 bool IsUseStrongLiteral() const {
871 return TypeField::decode(code_) == kStringLiteralExpression &&
872 IsUseStrongField::decode(code_);
875 bool IsThis() const {
876 return TypeField::decode(code_) == kExpression &&
877 ExpressionTypeField::decode(code_) == kThisExpression;
880 bool IsThisProperty() const {
881 return TypeField::decode(code_) == kExpression &&
882 ExpressionTypeField::decode(code_) == kThisPropertyExpression;
885 bool IsProperty() const {
886 return TypeField::decode(code_) == kExpression &&
887 (ExpressionTypeField::decode(code_) == kPropertyExpression ||
888 ExpressionTypeField::decode(code_) == kThisPropertyExpression);
891 bool IsCall() const {
892 return TypeField::decode(code_) == kExpression &&
893 ExpressionTypeField::decode(code_) == kCallExpression;
896 bool IsValidReferenceExpression() const {
897 return IsIdentifier() || IsProperty();
900 bool IsValidArrowParamList() const {
901 return IsValidArrowParams() &&
902 ParenthesizationField::decode(code_) !=
903 kMultiParenthesizedExpression;
906 // At the moment PreParser doesn't track these expression types.
907 bool IsFunctionLiteral() const { return false; }
908 bool IsCallNew() const { return false; }
910 bool IsNoTemplateTag() const {
911 return TypeField::decode(code_) == kExpression &&
912 ExpressionTypeField::decode(code_) == kNoTemplateTagExpression;
915 PreParserExpression AsFunctionLiteral() { return *this; }
917 bool IsBinaryOperation() const {
918 return TypeField::decode(code_) == kBinaryOperationExpression;
921 bool is_parenthesized() const {
922 return ParenthesizationField::decode(code_) != kNotParenthesized;
925 void increase_parenthesization_level() {
926 code_ = ParenthesizationField::update(
927 code_, is_parenthesized() ? kMultiParenthesizedExpression
928 : kParanthesizedExpression);
931 // Dummy implementation for making expression->somefunc() work in both Parser
933 PreParserExpression* operator->() { return this; }
935 // More dummy implementations of things PreParser doesn't need to track:
936 void set_index(int index) {} // For YieldExpressions
937 void set_parenthesized() {}
939 int position() const { return RelocInfo::kNoPosition; }
940 void set_function_token_position(int position) {}
945 kIdentifierExpression,
946 kStringLiteralExpression,
947 kBinaryOperationExpression
950 enum Parenthesization {
952 kParanthesizedExpression,
953 kMultiParenthesizedExpression
956 enum ExpressionType {
958 kThisPropertyExpression,
962 kNoTemplateTagExpression
965 explicit PreParserExpression(uint32_t expression_code)
966 : code_(expression_code) {}
968 V8_INLINE bool IsValidArrowParams() const {
969 return IsBinaryOperation()
970 ? IsValidArrowParamListField::decode(code_)
971 : (IsIdentifier() && AsIdentifier().IsValidArrowParam());
974 // The first four bits are for the Type and Parenthesization.
975 typedef BitField<Type, 0, 2> TypeField;
976 typedef BitField<Parenthesization, TypeField::kNext, 2> ParenthesizationField;
978 // The rest of the bits are interpreted depending on the value
979 // of the Type field, so they can share the storage.
980 typedef BitField<ExpressionType, ParenthesizationField::kNext, 3>
982 typedef BitField<bool, ParenthesizationField::kNext, 1> IsUseStrictField;
983 typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseStrongField;
984 typedef BitField<bool, ParenthesizationField::kNext, 1>
985 IsValidArrowParamListField;
986 typedef BitField<PreParserIdentifier::Type, ParenthesizationField::kNext, 10>
993 // PreParserExpressionList doesn't actually store the expressions because
994 // PreParser doesn't need to.
995 class PreParserExpressionList {
997 // These functions make list->Add(some_expression) work (and do nothing).
998 PreParserExpressionList() : length_(0) {}
999 PreParserExpressionList* operator->() { return this; }
1000 void Add(PreParserExpression, void*) { ++length_; }
1001 int length() const { return length_; }
1007 class PreParserStatement {
1009 static PreParserStatement Default() {
1010 return PreParserStatement(kUnknownStatement);
1013 static PreParserStatement FunctionDeclaration() {
1014 return PreParserStatement(kFunctionDeclaration);
1017 // Creates expression statement from expression.
1018 // Preserves being an unparenthesized string literal, possibly
1020 static PreParserStatement ExpressionStatement(
1021 PreParserExpression expression) {
1022 if (expression.IsUseStrictLiteral()) {
1023 return PreParserStatement(kUseStrictExpressionStatement);
1025 if (expression.IsUseStrongLiteral()) {
1026 return PreParserStatement(kUseStrongExpressionStatement);
1028 if (expression.IsStringLiteral()) {
1029 return PreParserStatement(kStringLiteralExpressionStatement);
1034 bool IsStringLiteral() {
1035 return code_ == kStringLiteralExpressionStatement;
1038 bool IsUseStrictLiteral() {
1039 return code_ == kUseStrictExpressionStatement;
1042 bool IsUseStrongLiteral() { return code_ == kUseStrongExpressionStatement; }
1044 bool IsFunctionDeclaration() {
1045 return code_ == kFunctionDeclaration;
1051 kStringLiteralExpressionStatement,
1052 kUseStrictExpressionStatement,
1053 kUseStrongExpressionStatement,
1054 kFunctionDeclaration
1057 explicit PreParserStatement(Type code) : code_(code) {}
1063 // PreParserStatementList doesn't actually store the statements because
1064 // the PreParser does not need them.
1065 class PreParserStatementList {
1067 // These functions make list->Add(some_expression) work as no-ops.
1068 PreParserStatementList() {}
1069 PreParserStatementList* operator->() { return this; }
1070 void Add(PreParserStatement, void*) {}
1074 class PreParserFactory {
1076 explicit PreParserFactory(void* unused_value_factory) {}
1077 PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
1079 return PreParserExpression::Default();
1081 PreParserExpression NewNumberLiteral(double number,
1083 return PreParserExpression::Default();
1085 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
1086 PreParserIdentifier js_flags,
1089 return PreParserExpression::Default();
1091 PreParserExpression NewArrayLiteral(PreParserExpressionList values,
1094 return PreParserExpression::Default();
1096 PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
1097 PreParserExpression value,
1098 ObjectLiteralProperty::Kind kind,
1100 bool is_computed_name) {
1101 return PreParserExpression::Default();
1103 PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
1104 PreParserExpression value,
1106 bool is_computed_name) {
1107 return PreParserExpression::Default();
1109 PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
1111 int boilerplate_properties,
1114 return PreParserExpression::Default();
1116 PreParserExpression NewVariableProxy(void* variable) {
1117 return PreParserExpression::Default();
1119 PreParserExpression NewProperty(PreParserExpression obj,
1120 PreParserExpression key,
1123 return PreParserExpression::ThisProperty();
1125 return PreParserExpression::Property();
1127 PreParserExpression NewUnaryOperation(Token::Value op,
1128 PreParserExpression expression,
1130 return PreParserExpression::Default();
1132 PreParserExpression NewBinaryOperation(Token::Value op,
1133 PreParserExpression left,
1134 PreParserExpression right, int pos) {
1135 return PreParserExpression::BinaryOperation(left, op, right);
1137 PreParserExpression NewCompareOperation(Token::Value op,
1138 PreParserExpression left,
1139 PreParserExpression right, int pos) {
1140 return PreParserExpression::Default();
1142 PreParserExpression NewAssignment(Token::Value op,
1143 PreParserExpression left,
1144 PreParserExpression right,
1146 return PreParserExpression::Default();
1148 PreParserExpression NewYield(PreParserExpression generator_object,
1149 PreParserExpression expression,
1150 Yield::Kind yield_kind,
1152 return PreParserExpression::Default();
1154 PreParserExpression NewConditional(PreParserExpression condition,
1155 PreParserExpression then_expression,
1156 PreParserExpression else_expression,
1158 return PreParserExpression::Default();
1160 PreParserExpression NewCountOperation(Token::Value op,
1162 PreParserExpression expression,
1164 return PreParserExpression::Default();
1166 PreParserExpression NewCall(PreParserExpression expression,
1167 PreParserExpressionList arguments,
1169 return PreParserExpression::Call();
1171 PreParserExpression NewCallNew(PreParserExpression expression,
1172 PreParserExpressionList arguments,
1174 return PreParserExpression::Default();
1176 PreParserStatement NewReturnStatement(PreParserExpression expression,
1178 return PreParserStatement::Default();
1180 PreParserExpression NewFunctionLiteral(
1181 PreParserIdentifier name, AstValueFactory* ast_value_factory,
1182 Scope* scope, PreParserStatementList body, int materialized_literal_count,
1183 int expected_property_count, int handler_count, int parameter_count,
1184 FunctionLiteral::ParameterFlag has_duplicate_parameters,
1185 FunctionLiteral::FunctionType function_type,
1186 FunctionLiteral::IsFunctionFlag is_function,
1187 FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
1189 return PreParserExpression::Default();
1192 // Return the object itself as AstVisitor and implement the needed
1193 // dummy method right in this class.
1194 PreParserFactory* visitor() { return this; }
1195 int* ast_properties() {
1196 static int dummy = 42;
1204 class PreParserTraits {
1207 // TODO(marja): To be removed. The Traits object should contain all the data
1209 typedef PreParser* Parser;
1211 // PreParser doesn't need to store generator variables.
1212 typedef void GeneratorVariable;
1214 typedef int AstProperties;
1216 // Return types for traversing functions.
1217 typedef PreParserIdentifier Identifier;
1218 typedef PreParserExpression Expression;
1219 typedef PreParserExpression YieldExpression;
1220 typedef PreParserExpression FunctionLiteral;
1221 typedef PreParserExpression ClassLiteral;
1222 typedef PreParserExpression ObjectLiteralProperty;
1223 typedef PreParserExpression Literal;
1224 typedef PreParserExpressionList ExpressionList;
1225 typedef PreParserExpressionList PropertyList;
1226 typedef PreParserStatementList StatementList;
1228 // For constructing objects returned by the traversing functions.
1229 typedef PreParserFactory Factory;
1232 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
1234 // Helper functions for recursive descent.
1235 static bool IsEval(PreParserIdentifier identifier) {
1236 return identifier.IsEval();
1239 static bool IsArguments(PreParserIdentifier identifier) {
1240 return identifier.IsArguments();
1243 static bool IsEvalOrArguments(PreParserIdentifier identifier) {
1244 return identifier.IsEvalOrArguments();
1247 static bool IsPrototype(PreParserIdentifier identifier) {
1248 return identifier.IsPrototype();
1251 static bool IsConstructor(PreParserIdentifier identifier) {
1252 return identifier.IsConstructor();
1255 // Returns true if the expression is of type "this.foo".
1256 static bool IsThisProperty(PreParserExpression expression) {
1257 return expression.IsThisProperty();
1260 static bool IsIdentifier(PreParserExpression expression) {
1261 return expression.IsIdentifier();
1264 static PreParserIdentifier AsIdentifier(PreParserExpression expression) {
1265 return expression.AsIdentifier();
1268 static bool IsFutureStrictReserved(PreParserIdentifier identifier) {
1269 return identifier.IsFutureStrictReserved();
1272 static bool IsBoilerplateProperty(PreParserExpression property) {
1273 // PreParser doesn't count boilerplate properties.
1277 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
1281 static PreParserExpression GetPropertyValue(PreParserExpression property) {
1282 return PreParserExpression::Default();
1285 // Functions for encapsulating the differences between parsing and preparsing;
1286 // operations interleaved with the recursive descent.
1287 static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
1288 // PreParser should not use FuncNameInferrer.
1292 static void PushPropertyName(FuncNameInferrer* fni,
1293 PreParserExpression expression) {
1294 // PreParser should not use FuncNameInferrer.
1298 static void InferFunctionName(FuncNameInferrer* fni,
1299 PreParserExpression expression) {
1300 // PreParser should not use FuncNameInferrer.
1304 static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
1305 Scope* scope, PreParserExpression property, bool* has_function) {}
1307 static void CheckAssigningFunctionLiteralToProperty(
1308 PreParserExpression left, PreParserExpression right) {}
1310 // PreParser doesn't need to keep track of eval calls.
1311 static void CheckPossibleEvalCall(PreParserExpression expression,
1314 static PreParserExpression MarkExpressionAsAssigned(
1315 PreParserExpression expression) {
1316 // TODO(marja): To be able to produce the same errors, the preparser needs
1317 // to start tracking which expressions are variables and which are assigned.
1321 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
1322 PreParserExpression y,
1325 PreParserFactory* factory) {
1329 PreParserExpression BuildUnaryExpression(PreParserExpression expression,
1330 Token::Value op, int pos,
1331 PreParserFactory* factory) {
1332 return PreParserExpression::Default();
1335 PreParserExpression NewThrowReferenceError(const char* type, int pos) {
1336 return PreParserExpression::Default();
1338 PreParserExpression NewThrowSyntaxError(
1339 const char* type, Handle<Object> arg, int pos) {
1340 return PreParserExpression::Default();
1342 PreParserExpression NewThrowTypeError(
1343 const char* type, Handle<Object> arg, int pos) {
1344 return PreParserExpression::Default();
1347 // Reporting errors.
1348 void ReportMessageAt(Scanner::Location location,
1349 const char* message,
1350 const char* arg = NULL,
1351 bool is_reference_error = false);
1352 void ReportMessageAt(int start_pos,
1354 const char* message,
1355 const char* arg = NULL,
1356 bool is_reference_error = false);
1358 // "null" return type creators.
1359 static PreParserIdentifier EmptyIdentifier() {
1360 return PreParserIdentifier::Default();
1362 static PreParserIdentifier EmptyIdentifierString() {
1363 return PreParserIdentifier::Default();
1365 static PreParserExpression EmptyExpression() {
1366 return PreParserExpression::Default();
1368 static PreParserExpression EmptyArrowParamList() {
1369 return PreParserExpression::EmptyArrowParamList();
1371 static PreParserExpression EmptyLiteral() {
1372 return PreParserExpression::Default();
1374 static PreParserExpression EmptyObjectLiteralProperty() {
1375 return PreParserExpression::Default();
1377 static PreParserExpression EmptyFunctionLiteral() {
1378 return PreParserExpression::Default();
1380 static PreParserExpressionList NullExpressionList() {
1381 return PreParserExpressionList();
1384 // Odd-ball literal creators.
1385 static PreParserExpression GetLiteralTheHole(int position,
1386 PreParserFactory* factory) {
1387 return PreParserExpression::Default();
1390 // Producing data during the recursive descent.
1391 PreParserIdentifier GetSymbol(Scanner* scanner);
1392 PreParserIdentifier GetNumberAsSymbol(Scanner* scanner);
1394 static PreParserIdentifier GetNextSymbol(Scanner* scanner) {
1395 return PreParserIdentifier::Default();
1398 static PreParserExpression ThisExpression(Scope* scope,
1399 PreParserFactory* factory,
1401 return PreParserExpression::This();
1404 static PreParserExpression SuperReference(Scope* scope,
1405 PreParserFactory* factory) {
1406 return PreParserExpression::Super();
1409 static PreParserExpression DefaultConstructor(bool call_super, Scope* scope,
1410 int pos, int end_pos) {
1411 return PreParserExpression::Default();
1414 static PreParserExpression ExpressionFromLiteral(
1415 Token::Value token, int pos, Scanner* scanner,
1416 PreParserFactory* factory) {
1417 return PreParserExpression::Default();
1420 static PreParserExpression ExpressionFromIdentifier(
1421 PreParserIdentifier name, int pos, Scope* scope,
1422 PreParserFactory* factory) {
1423 return PreParserExpression::FromIdentifier(name);
1426 PreParserExpression ExpressionFromString(int pos,
1428 PreParserFactory* factory = NULL);
1430 PreParserExpression GetIterator(PreParserExpression iterable,
1431 PreParserFactory* factory) {
1432 return PreParserExpression::Default();
1435 static PreParserExpressionList NewExpressionList(int size, Zone* zone) {
1436 return PreParserExpressionList();
1439 static PreParserStatementList NewStatementList(int size, Zone* zone) {
1440 return PreParserStatementList();
1443 static PreParserExpressionList NewPropertyList(int size, Zone* zone) {
1444 return PreParserExpressionList();
1447 V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name,
1448 int* materialized_literal_count,
1449 int* expected_property_count, bool* ok) {
1453 V8_INLINE PreParserStatementList
1454 ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
1455 Variable* fvar, Token::Value fvar_init_op,
1456 FunctionKind kind, bool* ok);
1458 // Utility functions
1459 int DeclareArrowParametersFromExpression(PreParserExpression expression,
1461 Scanner::Location* dupe_loc,
1463 // TODO(aperez): Detect duplicated identifiers in paramlists.
1464 *ok = expression.IsValidArrowParamList();
1468 struct TemplateLiteralState {};
1470 TemplateLiteralState OpenTemplateLiteral(int pos) {
1471 return TemplateLiteralState();
1473 void AddTemplateSpan(TemplateLiteralState*, bool) {}
1474 void AddTemplateExpression(TemplateLiteralState*, PreParserExpression) {}
1475 PreParserExpression CloseTemplateLiteral(TemplateLiteralState*, int,
1476 PreParserExpression tag) {
1477 if (IsTaggedTemplate(tag)) {
1478 // Emulate generation of array literals for tag callsite
1479 // 1st is array of cooked strings, second is array of raw strings
1480 MaterializeTemplateCallsiteLiterals();
1482 return EmptyExpression();
1484 inline void MaterializeTemplateCallsiteLiterals();
1485 PreParserExpression NoTemplateTag() {
1486 return PreParserExpression::NoTemplateTag();
1488 static bool IsTaggedTemplate(const PreParserExpression tag) {
1489 return !tag.IsNoTemplateTag();
1492 void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}
1494 // Temporary glue; these functions will move to ParserBase.
1495 PreParserExpression ParseV8Intrinsic(bool* ok);
1496 PreParserExpression ParseFunctionLiteral(
1497 PreParserIdentifier name, Scanner::Location function_name_location,
1498 bool name_is_strict_reserved, FunctionKind kind,
1499 int function_token_position, FunctionLiteral::FunctionType type,
1500 FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
1502 PreParserExpression ParseClassLiteral(PreParserIdentifier name,
1503 Scanner::Location class_name_location,
1504 bool name_is_strict_reserved, int pos,
1508 PreParser* pre_parser_;
1512 // Preparsing checks a JavaScript program and emits preparse-data that helps
1513 // a later parsing to be faster.
1514 // See preparse-data-format.h for the data format.
1516 // The PreParser checks that the syntax follows the grammar for JavaScript,
1517 // and collects some information about the program along the way.
1518 // The grammar check is only performed in order to understand the program
1519 // sufficiently to deduce some information about it, that can be used
1520 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
1521 // rather it is to speed up properly written and correct programs.
1522 // That means that contextual checks (like a label being declared where
1523 // it is used) are generally omitted.
1524 class PreParser : public ParserBase<PreParserTraits> {
1526 typedef PreParserIdentifier Identifier;
1527 typedef PreParserExpression Expression;
1528 typedef PreParserStatement Statement;
1530 enum PreParseResult {
1531 kPreParseStackOverflow,
1535 PreParser(Zone* zone, Scanner* scanner, AstValueFactory* ast_value_factory,
1536 ParserRecorder* log, uintptr_t stack_limit)
1537 : ParserBase<PreParserTraits>(zone, scanner, stack_limit, NULL,
1538 ast_value_factory, log, this) {}
1540 // Pre-parse the program from the character stream; returns true on
1541 // success (even if parsing failed, the pre-parse data successfully
1542 // captured the syntax error), and false if a stack-overflow happened
1544 PreParseResult PreParseProgram(int* materialized_literals = 0) {
1545 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
1546 PreParserFactory factory(NULL);
1547 FunctionState top_scope(&function_state_, &scope_, scope, kNormalFunction,
1550 int start_position = scanner()->peek_location().beg_pos;
1551 ParseStatementList(Token::EOS, &ok);
1552 if (stack_overflow()) return kPreParseStackOverflow;
1554 ReportUnexpectedToken(scanner()->current_token());
1555 } else if (is_strict(scope_->language_mode())) {
1556 CheckStrictOctalLiteral(start_position, scanner()->location().end_pos,
1559 if (materialized_literals) {
1560 *materialized_literals = function_state_->materialized_literal_count();
1562 return kPreParseSuccess;
1565 // Parses a single function literal, from the opening parentheses before
1566 // parameters to the closing brace after the body.
1567 // Returns a FunctionEntry describing the body of the function in enough
1568 // detail that it can be lazily compiled.
1569 // The scanner is expected to have matched the "function" or "function*"
1570 // keyword and parameters, and have consumed the initial '{'.
1571 // At return, unless an error occurred, the scanner is positioned before the
1573 PreParseResult PreParseLazyFunction(LanguageMode language_mode,
1574 FunctionKind kind, ParserRecorder* log);
1577 friend class PreParserTraits;
1579 // These types form an algebra over syntactic categories that is just
1580 // rich enough to let us recognize and propagate the constructs that
1581 // are either being counted in the preparser data, or is important
1582 // to throw the correct syntax error exceptions.
1584 // All ParseXXX functions take as the last argument an *ok parameter
1585 // which is set to false if parsing failed; it is unchanged otherwise.
1586 // By making the 'exception handling' explicit, we are forced to check
1587 // for failure at the call sites.
1588 Statement ParseStatementListItem(bool* ok);
1589 void ParseStatementList(int end_token, bool* ok);
1590 Statement ParseStatement(bool* ok);
1591 Statement ParseSubStatement(bool* ok);
1592 Statement ParseFunctionDeclaration(bool* ok);
1593 Statement ParseClassDeclaration(bool* ok);
1594 Statement ParseBlock(bool* ok);
1595 Statement ParseVariableStatement(VariableDeclarationContext var_context,
1597 Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
1598 VariableDeclarationProperties* decl_props,
1601 Statement ParseExpressionOrLabelledStatement(bool* ok);
1602 Statement ParseIfStatement(bool* ok);
1603 Statement ParseContinueStatement(bool* ok);
1604 Statement ParseBreakStatement(bool* ok);
1605 Statement ParseReturnStatement(bool* ok);
1606 Statement ParseWithStatement(bool* ok);
1607 Statement ParseSwitchStatement(bool* ok);
1608 Statement ParseDoWhileStatement(bool* ok);
1609 Statement ParseWhileStatement(bool* ok);
1610 Statement ParseForStatement(bool* ok);
1611 Statement ParseThrowStatement(bool* ok);
1612 Statement ParseTryStatement(bool* ok);
1613 Statement ParseDebuggerStatement(bool* ok);
1614 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
1615 Expression ParseObjectLiteral(bool* ok);
1616 Expression ParseV8Intrinsic(bool* ok);
1618 V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name,
1619 int* materialized_literal_count,
1620 int* expected_property_count, bool* ok);
1621 V8_INLINE PreParserStatementList
1622 ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
1623 Variable* fvar, Token::Value fvar_init_op,
1624 FunctionKind kind, bool* ok);
1626 Expression ParseFunctionLiteral(
1627 Identifier name, Scanner::Location function_name_location,
1628 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
1629 FunctionLiteral::FunctionType function_type,
1630 FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
1631 void ParseLazyFunctionLiteralBody(bool* ok);
1633 PreParserExpression ParseClassLiteral(PreParserIdentifier name,
1634 Scanner::Location class_name_location,
1635 bool name_is_strict_reserved, int pos,
1640 void PreParserTraits::MaterializeTemplateCallsiteLiterals() {
1641 pre_parser_->function_state_->NextMaterializedLiteralIndex();
1642 pre_parser_->function_state_->NextMaterializedLiteralIndex();
1646 PreParserStatementList PreParser::ParseEagerFunctionBody(
1647 PreParserIdentifier function_name, int pos, Variable* fvar,
1648 Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
1649 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
1651 ParseStatementList(Token::RBRACE, ok);
1652 if (!*ok) return PreParserStatementList();
1654 Expect(Token::RBRACE, ok);
1655 return PreParserStatementList();
1659 PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
1660 PreParserIdentifier function_name, int pos, Variable* fvar,
1661 Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
1662 return pre_parser_->ParseEagerFunctionBody(function_name, pos, fvar,
1663 fvar_init_op, kind, ok);
1667 template <class Traits>
1668 ParserBase<Traits>::FunctionState::FunctionState(
1669 FunctionState** function_state_stack, Scope** scope_stack, Scope* scope,
1670 FunctionKind kind, typename Traits::Type::Factory* factory)
1671 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
1672 next_handler_index_(0),
1673 expected_property_count_(0),
1675 generator_object_variable_(NULL),
1676 function_state_stack_(function_state_stack),
1677 outer_function_state_(*function_state_stack),
1678 scope_stack_(scope_stack),
1679 outer_scope_(*scope_stack),
1681 *scope_stack_ = scope;
1682 *function_state_stack = this;
1686 template <class Traits>
1687 ParserBase<Traits>::FunctionState::~FunctionState() {
1688 *scope_stack_ = outer_scope_;
1689 *function_state_stack_ = outer_function_state_;
1693 template<class Traits>
1694 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
1695 Scanner::Location source_location = scanner()->location();
1697 // Four of the tokens are treated specially
1700 return ReportMessageAt(source_location, "unexpected_eos");
1702 return ReportMessageAt(source_location, "unexpected_token_number");
1704 return ReportMessageAt(source_location, "unexpected_token_string");
1705 case Token::IDENTIFIER:
1706 return ReportMessageAt(source_location, "unexpected_token_identifier");
1707 case Token::FUTURE_RESERVED_WORD:
1708 return ReportMessageAt(source_location, "unexpected_reserved");
1712 case Token::FUTURE_STRICT_RESERVED_WORD:
1713 return ReportMessageAt(source_location,
1714 is_strict(language_mode())
1715 ? "unexpected_strict_reserved"
1716 : "unexpected_token_identifier");
1717 case Token::TEMPLATE_SPAN:
1718 case Token::TEMPLATE_TAIL:
1719 return Traits::ReportMessageAt(source_location,
1720 "unexpected_template_string");
1722 const char* name = Token::String(token);
1723 DCHECK(name != NULL);
1724 Traits::ReportMessageAt(source_location, "unexpected_token", name);
1729 template<class Traits>
1730 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
1731 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
1733 Token::Value next = Next();
1734 if (next == Token::IDENTIFIER) {
1735 IdentifierT name = this->GetSymbol(scanner());
1736 if (allow_eval_or_arguments == kDontAllowEvalOrArguments) {
1737 if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) {
1738 ReportMessage("strict_eval_arguments");
1742 if (is_strong(language_mode()) && this->IsArguments(name)) {
1743 ReportMessage("strong_arguments");
1747 if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
1749 } else if (is_sloppy(language_mode()) &&
1750 (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1751 next == Token::LET || next == Token::STATIC ||
1752 (next == Token::YIELD && !is_generator()))) {
1753 return this->GetSymbol(scanner());
1755 this->ReportUnexpectedToken(next);
1757 return Traits::EmptyIdentifier();
1762 template <class Traits>
1763 typename ParserBase<Traits>::IdentifierT ParserBase<
1764 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
1766 Token::Value next = Next();
1767 if (next == Token::IDENTIFIER) {
1768 *is_strict_reserved = false;
1769 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
1770 next == Token::STATIC ||
1771 (next == Token::YIELD && !this->is_generator())) {
1772 *is_strict_reserved = true;
1774 ReportUnexpectedToken(next);
1776 return Traits::EmptyIdentifier();
1779 IdentifierT name = this->GetSymbol(scanner());
1780 if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
1785 template <class Traits>
1786 typename ParserBase<Traits>::IdentifierT
1787 ParserBase<Traits>::ParseIdentifierName(bool* ok) {
1788 Token::Value next = Next();
1789 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
1790 next != Token::LET && next != Token::STATIC && next != Token::YIELD &&
1791 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
1792 this->ReportUnexpectedToken(next);
1794 return Traits::EmptyIdentifier();
1797 IdentifierT name = this->GetSymbol(scanner());
1798 if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
1803 template <class Traits>
1804 typename ParserBase<Traits>::IdentifierT
1805 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
1808 IdentifierT result = ParseIdentifierName(ok);
1809 if (!*ok) return Traits::EmptyIdentifier();
1810 scanner()->IsGetOrSet(is_get, is_set);
1815 template <class Traits>
1816 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
1817 bool seen_equal, bool* ok) {
1818 int pos = peek_position();
1819 if (!scanner()->ScanRegExpPattern(seen_equal)) {
1821 ReportMessage("unterminated_regexp");
1823 return Traits::EmptyExpression();
1826 int literal_index = function_state_->NextMaterializedLiteralIndex();
1828 IdentifierT js_pattern = this->GetNextSymbol(scanner());
1829 if (!scanner()->ScanRegExpFlags()) {
1831 ReportMessage("malformed_regexp_flags");
1833 return Traits::EmptyExpression();
1835 IdentifierT js_flags = this->GetNextSymbol(scanner());
1837 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
1841 #define CHECK_OK ok); \
1842 if (!*ok) return this->EmptyExpression(); \
1844 #define DUMMY ) // to make indentation work
1847 // Used in functions where the return type is not ExpressionT.
1848 #define CHECK_OK_CUSTOM(x) ok); \
1849 if (!*ok) return this->x(); \
1851 #define DUMMY ) // to make indentation work
1854 template <class Traits>
1855 typename ParserBase<Traits>::ExpressionT
1856 ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
1857 // PrimaryExpression ::
1869 // '(' Expression ')'
1872 int pos = peek_position();
1873 ExpressionT result = this->EmptyExpression();
1874 Token::Value token = peek();
1877 Consume(Token::THIS);
1878 scope_->RecordThisUsage();
1879 result = this->ThisExpression(scope_, factory(), pos);
1883 case Token::NULL_LITERAL:
1884 case Token::TRUE_LITERAL:
1885 case Token::FALSE_LITERAL:
1888 result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
1891 case Token::IDENTIFIER:
1895 case Token::FUTURE_STRICT_RESERVED_WORD: {
1896 // Using eval or arguments in this context is OK even in strict mode.
1897 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1898 result = this->ExpressionFromIdentifier(name, pos, scope_, factory());
1902 case Token::STRING: {
1903 Consume(Token::STRING);
1904 result = this->ExpressionFromString(pos, scanner(), factory());
1908 case Token::ASSIGN_DIV:
1909 result = this->ParseRegExpLiteral(true, CHECK_OK);
1913 result = this->ParseRegExpLiteral(false, CHECK_OK);
1917 result = this->ParseArrayLiteral(CHECK_OK);
1921 result = this->ParseObjectLiteral(CHECK_OK);
1925 Consume(Token::LPAREN);
1926 if (allow_harmony_arrow_functions() && peek() == Token::RPAREN) {
1927 // Arrow functions are the only expression type constructions
1928 // for which an empty parameter list "()" is valid input.
1929 Consume(Token::RPAREN);
1930 result = this->ParseArrowFunctionLiteral(
1931 pos, this->EmptyArrowParamList(), CHECK_OK);
1933 // Heuristically try to detect immediately called functions before
1934 // seeing the call parentheses.
1935 parenthesized_function_ = (peek() == Token::FUNCTION);
1936 result = this->ParseExpression(true, CHECK_OK);
1937 result->increase_parenthesization_level();
1938 Expect(Token::RPAREN, CHECK_OK);
1942 case Token::CLASS: {
1943 Consume(Token::CLASS);
1944 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
1945 ReportMessage("sloppy_lexical", NULL);
1949 int class_token_position = position();
1950 IdentifierT name = this->EmptyIdentifier();
1951 bool is_strict_reserved_name = false;
1952 Scanner::Location class_name_location = Scanner::Location::invalid();
1953 if (peek_any_identifier()) {
1954 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
1956 class_name_location = scanner()->location();
1958 result = this->ParseClassLiteral(name, class_name_location,
1959 is_strict_reserved_name,
1960 class_token_position, CHECK_OK);
1964 case Token::TEMPLATE_SPAN:
1965 case Token::TEMPLATE_TAIL:
1967 this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos, CHECK_OK);
1971 if (allow_natives() || extension_ != NULL) {
1972 result = this->ParseV8Intrinsic(CHECK_OK);
1975 // If we're not allowing special syntax we fall-through to the
1980 ReportUnexpectedToken(token);
1989 template <class Traits>
1990 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
1991 bool accept_IN, bool* ok) {
1993 // AssignmentExpression
1994 // Expression ',' AssignmentExpression
1996 ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1997 while (peek() == Token::COMMA) {
1998 Expect(Token::COMMA, CHECK_OK);
1999 int pos = position();
2000 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
2001 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
2007 template <class Traits>
2008 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
2011 // '[' Expression? (',' Expression?)* ']'
2013 int pos = peek_position();
2014 typename Traits::Type::ExpressionList values =
2015 this->NewExpressionList(4, zone_);
2016 Expect(Token::LBRACK, CHECK_OK);
2017 while (peek() != Token::RBRACK) {
2018 ExpressionT elem = this->EmptyExpression();
2019 if (peek() == Token::COMMA) {
2020 elem = this->GetLiteralTheHole(peek_position(), factory());
2022 elem = this->ParseAssignmentExpression(true, CHECK_OK);
2024 values->Add(elem, zone_);
2025 if (peek() != Token::RBRACK) {
2026 Expect(Token::COMMA, CHECK_OK);
2029 Expect(Token::RBRACK, CHECK_OK);
2031 // Update the scope information before the pre-parsing bailout.
2032 int literal_index = function_state_->NextMaterializedLiteralIndex();
2034 return factory()->NewArrayLiteral(values, literal_index, pos);
2038 template <class Traits>
2039 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
2040 IdentifierT* name, bool* is_get, bool* is_set, bool* is_static,
2041 bool* is_computed_name, bool* ok) {
2042 Token::Value token = peek();
2043 int pos = peek_position();
2045 // For non computed property names we normalize the name a bit:
2050 // identifier -> "identifier"
2052 // This is important because we use the property name as a key in a hash
2053 // table when we compute constant properties.
2056 Consume(Token::STRING);
2057 *name = this->GetSymbol(scanner());
2061 Consume(Token::NUMBER);
2062 *name = this->GetNumberAsSymbol(scanner());
2066 if (allow_harmony_computed_property_names_) {
2067 *is_computed_name = true;
2068 Consume(Token::LBRACK);
2069 ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK);
2070 Expect(Token::RBRACK, CHECK_OK);
2080 *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK);
2085 return this->IsArrayIndex(*name, &index)
2086 ? factory()->NewNumberLiteral(index, pos)
2087 : factory()->NewStringLiteral(*name, pos);
2091 template <class Traits>
2092 typename ParserBase<Traits>::ObjectLiteralPropertyT
2093 ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
2094 bool in_class, bool has_extends,
2096 bool* is_computed_name,
2097 bool* has_seen_constructor,
2099 DCHECK(!in_class || is_static || has_seen_constructor != nullptr);
2100 ExpressionT value = this->EmptyExpression();
2101 IdentifierT name = this->EmptyIdentifier();
2102 bool is_get = false;
2103 bool is_set = false;
2104 bool name_is_static = false;
2105 bool is_generator = allow_harmony_object_literals_ && Check(Token::MUL);
2107 Token::Value name_token = peek();
2108 int next_pos = peek_position();
2109 ExpressionT name_expression = ParsePropertyName(
2110 &name, &is_get, &is_set, &name_is_static, is_computed_name,
2111 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2113 if (fni_ != nullptr && !*is_computed_name) {
2114 this->PushLiteralName(fni_, name);
2117 if (!in_class && !is_generator && peek() == Token::COLON) {
2118 // PropertyDefinition : PropertyName ':' AssignmentExpression
2119 if (!*is_computed_name) {
2120 checker->CheckProperty(name_token, kValueProperty, is_static,
2122 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2124 Consume(Token::COLON);
2125 value = this->ParseAssignmentExpression(
2126 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2128 } else if (is_generator ||
2129 (allow_harmony_object_literals_ && peek() == Token::LPAREN)) {
2131 if (!*is_computed_name) {
2132 checker->CheckProperty(name_token, kMethodProperty, is_static,
2134 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2137 FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod
2138 : FunctionKind::kConciseMethod;
2140 if (in_class && !is_static && this->IsConstructor(name)) {
2141 *has_seen_constructor = true;
2142 kind = has_extends ? FunctionKind::kSubclassConstructor
2143 : FunctionKind::kBaseConstructor;
2146 value = this->ParseFunctionLiteral(
2147 name, scanner()->location(),
2148 false, // reserved words are allowed here
2149 kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
2150 FunctionLiteral::NORMAL_ARITY,
2151 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2153 return factory()->NewObjectLiteralProperty(name_expression, value,
2154 ObjectLiteralProperty::COMPUTED,
2155 is_static, *is_computed_name);
2157 } else if (in_class && name_is_static && !is_static) {
2158 // static MethodDefinition
2159 return ParsePropertyDefinition(checker, true, has_extends, true,
2160 is_computed_name, nullptr, ok);
2161 } else if (is_get || is_set) {
2163 name = this->EmptyIdentifier();
2164 bool dont_care = false;
2165 name_token = peek();
2167 name_expression = ParsePropertyName(
2168 &name, &dont_care, &dont_care, &dont_care, is_computed_name,
2169 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2171 if (!*is_computed_name) {
2172 checker->CheckProperty(name_token, kAccessorProperty, is_static,
2174 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2177 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
2178 name, scanner()->location(),
2179 false, // reserved words are allowed here
2180 FunctionKind::kAccessorFunction, RelocInfo::kNoPosition,
2181 FunctionLiteral::ANONYMOUS_EXPRESSION,
2182 is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
2183 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2185 // Make sure the name expression is a string since we need a Name for
2186 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this
2187 // statically we can skip the extra runtime check.
2188 if (!*is_computed_name) {
2190 factory()->NewStringLiteral(name, name_expression->position());
2193 return factory()->NewObjectLiteralProperty(
2194 name_expression, value,
2195 is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER,
2196 is_static, *is_computed_name);
2198 } else if (!in_class && allow_harmony_object_literals_ &&
2199 Token::IsIdentifier(name_token, language_mode(),
2200 this->is_generator())) {
2201 DCHECK(!*is_computed_name);
2203 value = this->ExpressionFromIdentifier(name, next_pos, scope_, factory());
2204 return factory()->NewObjectLiteralProperty(
2205 name_expression, value, ObjectLiteralProperty::COMPUTED, false, false);
2208 Token::Value next = Next();
2209 ReportUnexpectedToken(next);
2211 return this->EmptyObjectLiteralProperty();
2214 return factory()->NewObjectLiteralProperty(name_expression, value, is_static,
2219 template <class Traits>
2220 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
2223 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
2225 int pos = peek_position();
2226 typename Traits::Type::PropertyList properties =
2227 this->NewPropertyList(4, zone_);
2228 int number_of_boilerplate_properties = 0;
2229 bool has_function = false;
2230 bool has_computed_names = false;
2231 ObjectLiteralChecker checker(this);
2233 Expect(Token::LBRACE, CHECK_OK);
2235 while (peek() != Token::RBRACE) {
2236 if (fni_ != nullptr) fni_->Enter();
2238 const bool in_class = false;
2239 const bool is_static = false;
2240 const bool has_extends = false;
2241 bool is_computed_name = false;
2242 ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
2243 &checker, in_class, has_extends, is_static, &is_computed_name, NULL,
2246 if (is_computed_name) {
2247 has_computed_names = true;
2250 // Mark top-level object literals that contain function literals and
2251 // pretenure the literal so it can be added as a constant function
2252 // property. (Parser only.)
2253 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property,
2256 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
2257 if (!has_computed_names && this->IsBoilerplateProperty(property)) {
2258 number_of_boilerplate_properties++;
2260 properties->Add(property, zone());
2262 if (peek() != Token::RBRACE) {
2263 // Need {} because of the CHECK_OK macro.
2264 Expect(Token::COMMA, CHECK_OK);
2267 if (fni_ != nullptr) {
2272 Expect(Token::RBRACE, CHECK_OK);
2274 // Computation of literal_index must happen before pre parse bailout.
2275 int literal_index = function_state_->NextMaterializedLiteralIndex();
2277 return factory()->NewObjectLiteral(properties,
2279 number_of_boilerplate_properties,
2285 template <class Traits>
2286 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
2289 // '(' (AssignmentExpression)*[','] ')'
2291 typename Traits::Type::ExpressionList result =
2292 this->NewExpressionList(4, zone_);
2293 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
2294 bool done = (peek() == Token::RPAREN);
2296 ExpressionT argument = this->ParseAssignmentExpression(
2297 true, CHECK_OK_CUSTOM(NullExpressionList));
2298 result->Add(argument, zone_);
2299 if (result->length() > Code::kMaxArguments) {
2300 ReportMessage("too_many_arguments");
2302 return this->NullExpressionList();
2304 done = (peek() == Token::RPAREN);
2306 // Need {} because of the CHECK_OK_CUSTOM macro.
2307 Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList));
2310 Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
2315 template <class Traits>
2316 typename ParserBase<Traits>::ExpressionT
2317 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2318 // AssignmentExpression ::
2319 // ConditionalExpression
2322 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2324 Scanner::Location lhs_location = scanner()->peek_location();
2326 if (peek() == Token::YIELD && is_generator()) {
2327 return this->ParseYieldExpression(ok);
2330 if (fni_ != NULL) fni_->Enter();
2331 ParserBase<Traits>::Checkpoint checkpoint(this);
2332 ExpressionT expression =
2333 this->ParseConditionalExpression(accept_IN, CHECK_OK);
2335 if (allow_harmony_arrow_functions() && peek() == Token::ARROW) {
2336 checkpoint.Restore();
2337 expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos,
2338 expression, CHECK_OK);
2342 if (!Token::IsAssignmentOp(peek())) {
2343 if (fni_ != NULL) fni_->Leave();
2344 // Parsed conditional expression only (no assignment).
2348 expression = this->CheckAndRewriteReferenceExpression(
2349 expression, lhs_location, "invalid_lhs_in_assignment", CHECK_OK);
2350 expression = this->MarkExpressionAsAssigned(expression);
2352 Token::Value op = Next(); // Get assignment operator.
2353 int pos = position();
2354 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
2356 // TODO(1231235): We try to estimate the set of properties set by
2357 // constructors. We define a new property whenever there is an
2358 // assignment to a property of 'this'. We should probably only add
2359 // properties if we haven't seen them before. Otherwise we'll
2360 // probably overestimate the number of properties.
2361 if (op == Token::ASSIGN && this->IsThisProperty(expression)) {
2362 function_state_->AddProperty();
2365 this->CheckAssigningFunctionLiteralToProperty(expression, right);
2368 // Check if the right hand side is a call to avoid inferring a
2369 // name if we're dealing with "a = function(){...}();"-like
2371 if ((op == Token::INIT_VAR
2372 || op == Token::INIT_CONST_LEGACY
2373 || op == Token::ASSIGN)
2374 && (!right->IsCall() && !right->IsCallNew())) {
2377 fni_->RemoveLastFunction();
2382 return factory()->NewAssignment(op, expression, right, pos);
2385 template <class Traits>
2386 typename ParserBase<Traits>::ExpressionT
2387 ParserBase<Traits>::ParseYieldExpression(bool* ok) {
2388 // YieldExpression ::
2389 // 'yield' ([no line terminator] '*'? AssignmentExpression)?
2390 int pos = peek_position();
2391 Expect(Token::YIELD, CHECK_OK);
2392 ExpressionT generator_object =
2393 factory()->NewVariableProxy(function_state_->generator_object_variable());
2394 ExpressionT expression = Traits::EmptyExpression();
2395 Yield::Kind kind = Yield::kSuspend;
2396 if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
2397 if (Check(Token::MUL)) kind = Yield::kDelegating;
2400 case Token::SEMICOLON:
2406 // The above set of tokens is the complete set of tokens that can appear
2407 // after an AssignmentExpression, and none of them can start an
2408 // AssignmentExpression. This allows us to avoid looking for an RHS for
2409 // a Yield::kSuspend operation, given only one look-ahead token.
2410 if (kind == Yield::kSuspend)
2412 DCHECK_EQ(Yield::kDelegating, kind);
2413 // Delegating yields require an RHS; fall through.
2415 expression = ParseAssignmentExpression(false, CHECK_OK);
2419 if (kind == Yield::kDelegating) {
2420 // var iterator = subject[Symbol.iterator]();
2421 expression = this->GetIterator(expression, factory());
2423 typename Traits::Type::YieldExpression yield =
2424 factory()->NewYield(generator_object, expression, kind, pos);
2425 if (kind == Yield::kDelegating) {
2426 yield->set_index(function_state_->NextHandlerIndex());
2433 template <class Traits>
2434 typename ParserBase<Traits>::ExpressionT
2435 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
2436 // ConditionalExpression ::
2437 // LogicalOrExpression
2438 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2440 int pos = peek_position();
2441 // We start using the binary expression parser for prec >= 4 only!
2442 ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK);
2443 if (peek() != Token::CONDITIONAL) return expression;
2444 Consume(Token::CONDITIONAL);
2445 // In parsing the first assignment expression in conditional
2446 // expressions we always accept the 'in' keyword; see ECMA-262,
2447 // section 11.12, page 58.
2448 ExpressionT left = ParseAssignmentExpression(true, CHECK_OK);
2449 Expect(Token::COLON, CHECK_OK);
2450 ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2451 return factory()->NewConditional(expression, left, right, pos);
2456 template <class Traits>
2457 typename ParserBase<Traits>::ExpressionT
2458 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2460 ExpressionT x = this->ParseUnaryExpression(CHECK_OK);
2461 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2463 while (Precedence(peek(), accept_IN) == prec1) {
2464 Token::Value op = Next();
2465 Scanner::Location op_location = scanner()->location();
2466 int pos = position();
2467 ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2469 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
2474 // For now we distinguish between comparisons and other binary
2475 // operations. (We could combine the two and get rid of this
2476 // code and AST node eventually.)
2477 if (Token::IsCompareOp(op)) {
2478 // We have a comparison.
2479 Token::Value cmp = op;
2481 case Token::NE: cmp = Token::EQ; break;
2482 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2485 if (cmp == Token::EQ && is_strong(language_mode())) {
2486 ReportMessageAt(op_location, "strong_equal");
2488 return this->EmptyExpression();
2490 x = factory()->NewCompareOperation(cmp, x, y, pos);
2492 // The comparison was negated - add a NOT.
2493 x = factory()->NewUnaryOperation(Token::NOT, x, pos);
2497 // We have a "normal" binary operation.
2498 x = factory()->NewBinaryOperation(op, x, y, pos);
2506 template <class Traits>
2507 typename ParserBase<Traits>::ExpressionT
2508 ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
2509 // UnaryExpression ::
2510 // PostfixExpression
2511 // 'delete' UnaryExpression
2512 // 'void' UnaryExpression
2513 // 'typeof' UnaryExpression
2514 // '++' UnaryExpression
2515 // '--' UnaryExpression
2516 // '+' UnaryExpression
2517 // '-' UnaryExpression
2518 // '~' UnaryExpression
2519 // '!' UnaryExpression
2521 Token::Value op = peek();
2522 if (Token::IsUnaryOp(op)) {
2524 int pos = position();
2525 ExpressionT expression = ParseUnaryExpression(CHECK_OK);
2527 if (op == Token::DELETE && is_strict(language_mode())) {
2528 if (is_strong(language_mode())) {
2529 ReportMessage("strong_delete");
2531 return this->EmptyExpression();
2532 } else if (this->IsIdentifier(expression)) {
2533 // "delete identifier" is a syntax error in strict mode.
2534 ReportMessage("strict_delete");
2536 return this->EmptyExpression();
2540 // Allow Traits do rewrite the expression.
2541 return this->BuildUnaryExpression(expression, op, pos, factory());
2542 } else if (Token::IsCountOp(op)) {
2544 Scanner::Location lhs_location = scanner()->peek_location();
2545 ExpressionT expression = this->ParseUnaryExpression(CHECK_OK);
2546 expression = this->CheckAndRewriteReferenceExpression(
2547 expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK);
2548 this->MarkExpressionAsAssigned(expression);
2550 return factory()->NewCountOperation(op,
2556 return this->ParsePostfixExpression(ok);
2561 template <class Traits>
2562 typename ParserBase<Traits>::ExpressionT
2563 ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
2564 // PostfixExpression ::
2565 // LeftHandSideExpression ('++' | '--')?
2567 Scanner::Location lhs_location = scanner()->peek_location();
2568 ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK);
2569 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2570 Token::IsCountOp(peek())) {
2571 expression = this->CheckAndRewriteReferenceExpression(
2572 expression, lhs_location, "invalid_lhs_in_postfix_op", CHECK_OK);
2573 expression = this->MarkExpressionAsAssigned(expression);
2575 Token::Value next = Next();
2577 factory()->NewCountOperation(next,
2578 false /* postfix */,
2586 template <class Traits>
2587 typename ParserBase<Traits>::ExpressionT
2588 ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
2589 // LeftHandSideExpression ::
2590 // (NewExpression | MemberExpression) ...
2592 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
2596 case Token::LBRACK: {
2597 Consume(Token::LBRACK);
2598 int pos = position();
2599 ExpressionT index = ParseExpression(true, CHECK_OK);
2600 result = factory()->NewProperty(result, index, pos);
2601 Expect(Token::RBRACK, CHECK_OK);
2605 case Token::LPAREN: {
2607 if (scanner()->current_token() == Token::IDENTIFIER) {
2608 // For call of an identifier we want to report position of
2609 // the identifier as position of the call in the stack trace.
2612 // For other kinds of calls we record position of the parenthesis as
2613 // position of the call. Note that this is extremely important for
2614 // expressions of the form function(){...}() for which call position
2615 // should not point to the closing brace otherwise it will intersect
2616 // with positions recorded for function literal and confuse debugger.
2617 pos = peek_position();
2618 // Also the trailing parenthesis are a hint that the function will
2619 // be called immediately. If we happen to have parsed a preceding
2620 // function literal eagerly, we can also compile it eagerly.
2621 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
2622 result->AsFunctionLiteral()->set_parenthesized();
2625 typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK);
2627 // Keep track of eval() calls since they disable all local variable
2629 // The calls that need special treatment are the
2630 // direct eval calls. These calls are all of the form eval(...), with
2631 // no explicit receiver.
2632 // These calls are marked as potentially direct eval calls. Whether
2633 // they are actually direct calls to eval is determined at run time.
2634 this->CheckPossibleEvalCall(result, scope_);
2635 result = factory()->NewCall(result, args, pos);
2636 if (fni_ != NULL) fni_->RemoveLastFunction();
2640 case Token::TEMPLATE_SPAN:
2641 case Token::TEMPLATE_TAIL: {
2643 if (scanner()->current_token() == Token::IDENTIFIER) {
2646 pos = peek_position();
2647 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
2648 // If the tag function looks like an IIFE, set_parenthesized() to
2649 // force eager compilation.
2650 result->AsFunctionLiteral()->set_parenthesized();
2653 result = ParseTemplateLiteral(result, pos, CHECK_OK);
2657 case Token::PERIOD: {
2658 Consume(Token::PERIOD);
2659 int pos = position();
2660 IdentifierT name = ParseIdentifierName(CHECK_OK);
2661 result = factory()->NewProperty(
2662 result, factory()->NewStringLiteral(name, pos), pos);
2663 if (fni_ != NULL) this->PushLiteralName(fni_, name);
2674 template <class Traits>
2675 typename ParserBase<Traits>::ExpressionT
2676 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
2678 // ('new')+ MemberExpression
2680 // The grammar for new expressions is pretty warped. We can have several 'new'
2681 // keywords following each other, and then a MemberExpression. When we see '('
2682 // after the MemberExpression, it's associated with the rightmost unassociated
2683 // 'new' to create a NewExpression with arguments. However, a NewExpression
2684 // can also occur without arguments.
2686 // Examples of new expression:
2687 // new foo.bar().baz means (new (foo.bar)()).baz
2688 // new foo()() means (new foo())()
2689 // new new foo()() means (new (new foo())())
2690 // new new foo means new (new foo)
2691 // new new foo() means new (new foo())
2692 // new new foo().bar().baz means (new (new foo()).bar()).baz
2694 if (peek() == Token::NEW) {
2695 Consume(Token::NEW);
2696 int new_pos = position();
2697 ExpressionT result = this->EmptyExpression();
2698 if (peek() == Token::SUPER) {
2699 const bool is_new = true;
2700 result = ParseSuperExpression(is_new, CHECK_OK);
2702 result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
2704 if (peek() == Token::LPAREN) {
2705 // NewExpression with arguments.
2706 typename Traits::Type::ExpressionList args =
2707 this->ParseArguments(CHECK_OK);
2708 result = factory()->NewCallNew(result, args, new_pos);
2709 // The expression can still continue with . or [ after the arguments.
2710 result = this->ParseMemberExpressionContinuation(result, CHECK_OK);
2713 // NewExpression without arguments.
2714 return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
2717 // No 'new' or 'super' keyword.
2718 return this->ParseMemberExpression(ok);
2722 template <class Traits>
2723 typename ParserBase<Traits>::ExpressionT
2724 ParserBase<Traits>::ParseMemberExpression(bool* ok) {
2725 // MemberExpression ::
2726 // (PrimaryExpression | FunctionLiteral | ClassLiteral)
2727 // ('[' Expression ']' | '.' Identifier | Arguments)*
2729 // The '[' Expression ']' and '.' Identifier parts are parsed by
2730 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
2733 // Parse the initial primary or function expression.
2734 ExpressionT result = this->EmptyExpression();
2735 if (peek() == Token::FUNCTION) {
2736 Consume(Token::FUNCTION);
2737 int function_token_position = position();
2738 bool is_generator = Check(Token::MUL);
2739 IdentifierT name = this->EmptyIdentifier();
2740 bool is_strict_reserved_name = false;
2741 Scanner::Location function_name_location = Scanner::Location::invalid();
2742 FunctionLiteral::FunctionType function_type =
2743 FunctionLiteral::ANONYMOUS_EXPRESSION;
2744 if (peek_any_identifier()) {
2745 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
2747 function_name_location = scanner()->location();
2748 function_type = FunctionLiteral::NAMED_EXPRESSION;
2750 result = this->ParseFunctionLiteral(
2751 name, function_name_location, is_strict_reserved_name,
2752 is_generator ? FunctionKind::kGeneratorFunction
2753 : FunctionKind::kNormalFunction,
2754 function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
2756 } else if (peek() == Token::SUPER) {
2757 const bool is_new = false;
2758 result = ParseSuperExpression(is_new, CHECK_OK);
2760 result = ParsePrimaryExpression(CHECK_OK);
2763 result = ParseMemberExpressionContinuation(result, CHECK_OK);
2768 template <class Traits>
2769 typename ParserBase<Traits>::ExpressionT
2770 ParserBase<Traits>::ParseSuperExpression(bool is_new, bool* ok) {
2771 Expect(Token::SUPER, CHECK_OK);
2773 FunctionState* function_state = function_state_;
2774 while (IsArrowFunction(function_state->kind())) {
2775 function_state = function_state->outer();
2777 // TODO(arv): Handle eval scopes similarly.
2779 FunctionKind kind = function_state->kind();
2780 if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
2781 i::IsConstructor(kind)) {
2782 if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
2783 scope_->RecordSuperPropertyUsage();
2784 return this->SuperReference(scope_, factory());
2786 // new super() is never allowed.
2787 // super() is only allowed in derived constructor
2788 if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) {
2789 return this->SuperReference(scope_, factory());
2793 ReportMessageAt(scanner()->location(), "unexpected_super");
2795 return this->EmptyExpression();
2799 template <class Traits>
2800 typename ParserBase<Traits>::ExpressionT
2801 ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
2803 // Parses this part of MemberExpression:
2804 // ('[' Expression ']' | '.' Identifier)*
2807 case Token::LBRACK: {
2808 Consume(Token::LBRACK);
2809 int pos = position();
2810 ExpressionT index = this->ParseExpression(true, CHECK_OK);
2811 expression = factory()->NewProperty(expression, index, pos);
2813 this->PushPropertyName(fni_, index);
2815 Expect(Token::RBRACK, CHECK_OK);
2818 case Token::PERIOD: {
2819 Consume(Token::PERIOD);
2820 int pos = position();
2821 IdentifierT name = ParseIdentifierName(CHECK_OK);
2822 expression = factory()->NewProperty(
2823 expression, factory()->NewStringLiteral(name, pos), pos);
2825 this->PushLiteralName(fni_, name);
2834 return this->EmptyExpression();
2838 template <class Traits>
2839 typename ParserBase<Traits>::ExpressionT
2840 ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos,
2841 ExpressionT params_ast,
2843 Scope* scope = this->NewScope(scope_, ARROW_SCOPE);
2844 typename Traits::Type::StatementList body;
2845 int num_parameters = -1;
2846 int materialized_literal_count = -1;
2847 int expected_property_count = -1;
2848 int handler_count = 0;
2851 typename Traits::Type::Factory function_factory(ast_value_factory());
2852 FunctionState function_state(&function_state_, &scope_, scope,
2853 kArrowFunction, &function_factory);
2854 Scanner::Location dupe_error_loc = Scanner::Location::invalid();
2855 // TODO(arv): Pass in eval_args_error_loc and reserved_loc here.
2856 num_parameters = Traits::DeclareArrowParametersFromExpression(
2857 params_ast, scope_, &dupe_error_loc, ok);
2860 Scanner::Location(start_pos, scanner()->location().beg_pos),
2861 "malformed_arrow_function_parameter_list");
2862 return this->EmptyExpression();
2865 if (num_parameters > Code::kMaxArguments) {
2866 ReportMessageAt(Scanner::Location(params_ast->position(), position()),
2867 "too_many_parameters");
2869 return this->EmptyExpression();
2872 Expect(Token::ARROW, CHECK_OK);
2874 if (peek() == Token::LBRACE) {
2875 // Multiple statemente body
2876 Consume(Token::LBRACE);
2877 bool is_lazily_parsed =
2878 (mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation());
2879 if (is_lazily_parsed) {
2880 body = this->NewStatementList(0, zone());
2881 this->SkipLazyFunctionBody(this->EmptyIdentifier(),
2882 &materialized_literal_count,
2883 &expected_property_count, CHECK_OK);
2885 body = this->ParseEagerFunctionBody(
2886 this->EmptyIdentifier(), RelocInfo::kNoPosition, NULL,
2887 Token::INIT_VAR, kArrowFunction, CHECK_OK);
2888 materialized_literal_count =
2889 function_state.materialized_literal_count();
2890 expected_property_count = function_state.expected_property_count();
2891 handler_count = function_state.handler_count();
2894 // Single-expression body
2895 int pos = position();
2896 parenthesized_function_ = false;
2897 ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK);
2898 body = this->NewStatementList(1, zone());
2899 body->Add(factory()->NewReturnStatement(expression, pos), zone());
2900 materialized_literal_count = function_state.materialized_literal_count();
2901 expected_property_count = function_state.expected_property_count();
2902 handler_count = function_state.handler_count();
2905 scope->set_start_position(start_pos);
2906 scope->set_end_position(scanner()->location().end_pos);
2908 // Arrow function *parameter lists* are always checked as in strict mode.
2909 // TODO(arv): eval_args_error_loc and reserved_loc needs to be set by
2910 // DeclareArrowParametersFromExpression.
2911 Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
2912 Scanner::Location reserved_loc = Scanner::Location::invalid();
2913 const bool use_strict_params = true;
2914 this->CheckFunctionParameterNames(language_mode(), use_strict_params,
2915 eval_args_error_loc, dupe_error_loc, reserved_loc, CHECK_OK);
2917 // Validate strict mode.
2918 if (is_strict(language_mode())) {
2919 CheckStrictOctalLiteral(start_pos, scanner()->location().end_pos,
2923 if (allow_harmony_scoping() && is_strict(language_mode()))
2924 this->CheckConflictingVarDeclarations(scope, CHECK_OK);
2927 FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
2928 this->EmptyIdentifierString(), ast_value_factory(), scope, body,
2929 materialized_literal_count, expected_property_count, handler_count,
2930 num_parameters, FunctionLiteral::kNoDuplicateParameters,
2931 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
2932 FunctionLiteral::kNotParenthesized, FunctionKind::kArrowFunction,
2935 function_literal->set_function_token_position(start_pos);
2937 if (fni_ != NULL) this->InferFunctionName(fni_, function_literal);
2939 return function_literal;
2943 template <typename Traits>
2944 typename ParserBase<Traits>::ExpressionT
2945 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
2946 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
2947 // text followed by a substitution expression), finalized by a single
2950 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
2951 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
2952 // NoSubstitutionTemplate.
2954 // When parsing a TemplateLiteral, we must have scanned either an initial
2955 // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
2956 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
2958 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
2959 // In this case we may simply consume the token and build a template with a
2960 // single TEMPLATE_SPAN and no expressions.
2961 if (peek() == Token::TEMPLATE_TAIL) {
2962 Consume(Token::TEMPLATE_TAIL);
2963 int pos = position();
2964 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
2965 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2966 Traits::AddTemplateSpan(&ts, true);
2967 return Traits::CloseTemplateLiteral(&ts, start, tag);
2970 Consume(Token::TEMPLATE_SPAN);
2971 int pos = position();
2972 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
2973 Traits::AddTemplateSpan(&ts, false);
2976 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
2977 // and repeat if the following token is a TEMPLATE_SPAN as well (in this
2978 // case, representing a TemplateMiddle).
2981 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
2983 if (next == Token::EOS) {
2984 ReportMessageAt(Scanner::Location(start, peek_position()),
2985 "unterminated_template");
2987 return Traits::EmptyExpression();
2988 } else if (next == Token::ILLEGAL) {
2989 Traits::ReportMessageAt(
2990 Scanner::Location(position() + 1, peek_position()),
2991 "unexpected_token", "ILLEGAL", false);
2993 return Traits::EmptyExpression();
2996 int expr_pos = peek_position();
2997 ExpressionT expression = this->ParseExpression(true, CHECK_OK);
2998 Traits::AddTemplateExpression(&ts, expression);
3000 if (peek() != Token::RBRACE) {
3001 ReportMessageAt(Scanner::Location(expr_pos, peek_position()),
3002 "unterminated_template_expr");
3004 return Traits::EmptyExpression();
3007 // If we didn't die parsing that expression, our next token should be a
3008 // TEMPLATE_SPAN or TEMPLATE_TAIL.
3009 next = scanner()->ScanTemplateContinuation();
3013 if (next == Token::EOS) {
3014 ReportMessageAt(Scanner::Location(start, pos), "unterminated_template");
3016 return Traits::EmptyExpression();
3017 } else if (next == Token::ILLEGAL) {
3018 Traits::ReportMessageAt(
3019 Scanner::Location(position() + 1, peek_position()),
3020 "unexpected_token", "ILLEGAL", false);
3022 return Traits::EmptyExpression();
3025 Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL);
3026 } while (next == Token::TEMPLATE_SPAN);
3028 DCHECK_EQ(next, Token::TEMPLATE_TAIL);
3029 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
3030 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
3031 return Traits::CloseTemplateLiteral(&ts, start, tag);
3035 template <typename Traits>
3036 typename ParserBase<Traits>::ExpressionT ParserBase<
3037 Traits>::CheckAndRewriteReferenceExpression(ExpressionT expression,
3038 Scanner::Location location,
3039 const char* message, bool* ok) {
3040 if (is_strict(language_mode()) && this->IsIdentifier(expression) &&
3041 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
3042 this->ReportMessageAt(location, "strict_eval_arguments", false);
3044 return this->EmptyExpression();
3045 } else if (expression->IsValidReferenceExpression()) {
3047 } else if (expression->IsCall()) {
3048 // If it is a call, make it a runtime error for legacy web compatibility.
3049 // Rewrite `expr' to `expr[throw ReferenceError]'.
3050 int pos = location.beg_pos;
3051 ExpressionT error = this->NewThrowReferenceError(message, pos);
3052 return factory()->NewProperty(expression, error, pos);
3054 this->ReportMessageAt(location, message, true);
3056 return this->EmptyExpression();
3062 #undef CHECK_OK_CUSTOM
3065 template <typename Traits>
3066 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
3067 Token::Value property, PropertyKind type, bool is_static, bool is_generator,
3070 DCHECK(!is_generator || type == kMethodProperty);
3072 if (property == Token::NUMBER) return;
3074 if (type == kValueProperty && IsProto()) {
3075 if (has_seen_proto_) {
3076 this->parser()->ReportMessage("duplicate_proto");
3080 has_seen_proto_ = true;
3086 template <typename Traits>
3087 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty(
3088 Token::Value property, PropertyKind type, bool is_static, bool is_generator,
3090 DCHECK(type == kMethodProperty || type == kAccessorProperty);
3092 if (property == Token::NUMBER) return;
3095 if (IsPrototype()) {
3096 this->parser()->ReportMessage("static_prototype");
3100 } else if (IsConstructor()) {
3101 if (is_generator || type == kAccessorProperty) {
3102 this->parser()->ReportMessage("constructor_special_method");
3106 if (has_seen_constructor_) {
3107 this->parser()->ReportMessage("duplicate_constructor");
3111 has_seen_constructor_ = true;
3117 #endif // V8_PREPARSER_H