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.
8 #include "func-name-inferrer.h"
18 // Common base class shared between parser and pre-parser. Traits encapsulate
19 // the differences between Parser and PreParser:
21 // - Return types: For example, Parser functions return Expression* and
22 // PreParser functions return PreParserExpression.
24 // - Creating parse tree nodes: Parser generates an AST during the recursive
25 // descent. PreParser doesn't create a tree. Instead, it passes around minimal
26 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain
27 // just enough data for the upper layer functions. PreParserFactory is
28 // responsible for creating these dummy objects. It provides a similar kind of
29 // interface as AstNodeFactory, so ParserBase doesn't need to care which one is
32 // - Miscellanous other tasks interleaved with the recursive descent. For
33 // example, Parser keeps track of which function literals should be marked as
34 // pretenured, and PreParser doesn't care.
36 // The traits are expected to contain the following typedefs:
38 // // In particular...
40 // // Used by FunctionState and BlockState.
42 // typedef GeneratorVariable;
44 // // Return types for traversing functions.
45 // typedef Identifier;
46 // typedef Expression;
47 // typedef FunctionLiteral;
48 // typedef ObjectLiteralProperty;
50 // typedef ExpressionList;
51 // typedef PropertyList;
52 // // For constructing objects returned by the traversing functions.
58 template <typename Traits>
59 class ParserBase : public Traits {
61 // Shorten type names defined by Traits.
62 typedef typename Traits::Type::Expression ExpressionT;
63 typedef typename Traits::Type::Identifier IdentifierT;
65 ParserBase(Scanner* scanner, uintptr_t stack_limit,
66 v8::Extension* extension,
68 typename Traits::Type::Zone* zone,
69 typename Traits::Type::Parser this_object)
70 : Traits(this_object),
71 parenthesized_function_(false),
73 function_state_(NULL),
74 extension_(extension),
77 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
79 stack_limit_(stack_limit),
80 stack_overflow_(false),
82 allow_natives_syntax_(false),
83 allow_generators_(false),
87 // Getters that indicate whether certain syntactical constructs are
88 // allowed to be parsed by this instance of the parser.
89 bool allow_lazy() const { return allow_lazy_; }
90 bool allow_natives_syntax() const { return allow_natives_syntax_; }
91 bool allow_generators() const { return allow_generators_; }
92 bool allow_for_of() const { return allow_for_of_; }
93 bool allow_modules() const { return scanner()->HarmonyModules(); }
94 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
95 bool allow_harmony_numeric_literals() const {
96 return scanner()->HarmonyNumericLiterals();
99 // Setters that determine whether certain syntactical constructs are
100 // allowed to be parsed by this instance of the parser.
101 void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
102 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
103 void set_allow_generators(bool allow) { allow_generators_ = allow; }
104 void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
105 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
106 void set_allow_harmony_scoping(bool allow) {
107 scanner()->SetHarmonyScoping(allow);
109 void set_allow_harmony_numeric_literals(bool allow) {
110 scanner()->SetHarmonyNumericLiterals(allow);
114 enum AllowEvalOrArgumentsAsIdentifier {
115 kAllowEvalOrArguments,
116 kDontAllowEvalOrArguments
124 // ---------------------------------------------------------------------------
125 // FunctionState and BlockState together implement the parser's scope stack.
126 // The parser's current scope is in scope_. BlockState and FunctionState
127 // constructors push on the scope stack and the destructors pop. They are also
128 // used to hold the parser's per-function and per-block state.
129 class BlockState BASE_EMBEDDED {
131 BlockState(typename Traits::Type::Scope** scope_stack,
132 typename Traits::Type::Scope* scope)
133 : scope_stack_(scope_stack),
134 outer_scope_(*scope_stack),
136 *scope_stack_ = scope_;
138 ~BlockState() { *scope_stack_ = outer_scope_; }
141 typename Traits::Type::Scope** scope_stack_;
142 typename Traits::Type::Scope* outer_scope_;
143 typename Traits::Type::Scope* scope_;
146 class FunctionState BASE_EMBEDDED {
149 FunctionState** function_state_stack,
150 typename Traits::Type::Scope** scope_stack,
151 typename Traits::Type::Scope* scope,
152 typename Traits::Type::Zone* zone = NULL);
155 int NextMaterializedLiteralIndex() {
156 return next_materialized_literal_index_++;
158 int materialized_literal_count() {
159 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
162 int NextHandlerIndex() { return next_handler_index_++; }
163 int handler_count() { return next_handler_index_; }
165 void AddProperty() { expected_property_count_++; }
166 int expected_property_count() { return expected_property_count_; }
168 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
169 bool is_generator() const { return is_generator_; }
171 void set_generator_object_variable(
172 typename Traits::Type::GeneratorVariable* variable) {
173 ASSERT(variable != NULL);
174 ASSERT(!is_generator());
175 generator_object_variable_ = variable;
176 is_generator_ = true;
178 typename Traits::Type::GeneratorVariable* generator_object_variable()
180 return generator_object_variable_;
183 typename Traits::Type::Factory* factory() { return &factory_; }
186 // Used to assign an index to each literal that needs materialization in
187 // the function. Includes regexp literals, and boilerplate for object and
189 int next_materialized_literal_index_;
191 // Used to assign a per-function index to try and catch handlers.
192 int next_handler_index_;
194 // Properties count estimation.
195 int expected_property_count_;
197 // Whether the function is a generator.
199 // For generators, this variable may hold the generator object. It variable
200 // is used by yield expressions and return statements. It is not necessary
201 // for generator functions to have this variable set.
202 Variable* generator_object_variable_;
204 FunctionState** function_state_stack_;
205 FunctionState* outer_function_state_;
206 typename Traits::Type::Scope** scope_stack_;
207 typename Traits::Type::Scope* outer_scope_;
208 int saved_ast_node_id_; // Only used by ParserTraits.
209 typename Traits::Type::Zone* extra_param_;
210 typename Traits::Type::Factory factory_;
212 friend class ParserTraits;
215 class ParsingModeScope BASE_EMBEDDED {
217 ParsingModeScope(ParserBase* parser, Mode mode)
219 old_mode_(parser->mode()) {
220 parser_->mode_ = mode;
222 ~ParsingModeScope() {
223 parser_->mode_ = old_mode_;
231 Scanner* scanner() const { return scanner_; }
232 int position() { return scanner_->location().beg_pos; }
233 int peek_position() { return scanner_->peek_location().beg_pos; }
234 bool stack_overflow() const { return stack_overflow_; }
235 void set_stack_overflow() { stack_overflow_ = true; }
236 Mode mode() const { return mode_; }
237 typename Traits::Type::Zone* zone() const { return zone_; }
239 INLINE(Token::Value peek()) {
240 if (stack_overflow_) return Token::ILLEGAL;
241 return scanner()->peek();
244 INLINE(Token::Value Next()) {
245 if (stack_overflow_) return Token::ILLEGAL;
248 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
249 // Any further calls to Next or peek will return the illegal token.
250 // The current call must return the next token, which might already
251 // have been peek'ed.
252 stack_overflow_ = true;
255 return scanner()->Next();
258 void Consume(Token::Value token) {
259 Token::Value next = Next();
262 ASSERT(next == token);
265 bool Check(Token::Value token) {
266 Token::Value next = peek();
274 void Expect(Token::Value token, bool* ok) {
275 Token::Value next = Next();
277 ReportUnexpectedToken(next);
282 void ExpectSemicolon(bool* ok) {
283 // Check for automatic semicolon insertion according to
284 // the rules given in ECMA-262, section 7.9, page 21.
285 Token::Value tok = peek();
286 if (tok == Token::SEMICOLON) {
290 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
291 tok == Token::RBRACE ||
295 Expect(Token::SEMICOLON, ok);
298 bool peek_any_identifier() {
299 Token::Value next = peek();
300 return next == Token::IDENTIFIER ||
301 next == Token::FUTURE_RESERVED_WORD ||
302 next == Token::FUTURE_STRICT_RESERVED_WORD ||
303 next == Token::YIELD;
306 bool CheckContextualKeyword(Vector<const char> keyword) {
307 if (peek() == Token::IDENTIFIER &&
308 scanner()->is_next_contextual_keyword(keyword)) {
309 Consume(Token::IDENTIFIER);
315 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
316 Expect(Token::IDENTIFIER, ok);
318 if (!scanner()->is_literal_contextual_keyword(keyword)) {
319 ReportUnexpectedToken(scanner()->current_token());
324 // Checks whether an octal literal was last seen between beg_pos and end_pos.
325 // If so, reports an error. Only called for strict mode.
326 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
327 Scanner::Location octal = scanner()->octal_position();
328 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
329 octal.end_pos <= end_pos) {
330 ReportMessageAt(octal, "strict_octal_literal");
331 scanner()->clear_octal_position();
336 // Determine precedence of given token.
337 static int Precedence(Token::Value token, bool accept_IN) {
338 if (token == Token::IN && !accept_IN)
339 return 0; // 0 precedence will terminate binary expression parsing
340 return Token::Precedence(token);
343 typename Traits::Type::Factory* factory() {
344 return function_state_->factory();
347 StrictMode strict_mode() { return scope_->strict_mode(); }
348 bool is_generator() const { return function_state_->is_generator(); }
350 // Report syntax errors.
351 void ReportMessage(const char* message, Vector<const char*> args,
352 bool is_reference_error = false) {
353 Scanner::Location source_location = scanner()->location();
354 Traits::ReportMessageAt(source_location, message, args, is_reference_error);
357 void ReportMessageAt(Scanner::Location location, const char* message,
358 bool is_reference_error = false) {
359 Traits::ReportMessageAt(location, message, Vector<const char*>::empty(),
363 void ReportUnexpectedToken(Token::Value token);
365 // Recursive descent functions:
367 // Parses an identifier that is valid for the current scope, in particular it
368 // fails on strict mode future reserved keywords in a strict scope. If
369 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
370 // "arguments" as identifier even in strict mode (this is needed in cases like
371 // "var foo = eval;").
372 IdentifierT ParseIdentifier(
373 AllowEvalOrArgumentsAsIdentifier,
375 // Parses an identifier or a strict mode future reserved word, and indicate
376 // whether it is strict mode future reserved.
377 IdentifierT ParseIdentifierOrStrictReservedWord(
378 bool* is_strict_reserved,
380 IdentifierT ParseIdentifierName(bool* ok);
381 // Parses an identifier and determines whether or not it is 'get' or 'set'.
382 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get,
386 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok);
388 ExpressionT ParsePrimaryExpression(bool* ok);
389 ExpressionT ParseExpression(bool accept_IN, bool* ok);
390 ExpressionT ParseArrayLiteral(bool* ok);
391 ExpressionT ParseObjectLiteral(bool* ok);
392 typename Traits::Type::ExpressionList ParseArguments(bool* ok);
393 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
394 ExpressionT ParseYieldExpression(bool* ok);
395 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
396 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
397 ExpressionT ParseUnaryExpression(bool* ok);
398 ExpressionT ParsePostfixExpression(bool* ok);
399 ExpressionT ParseLeftHandSideExpression(bool* ok);
400 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
401 ExpressionT ParseMemberExpression(bool* ok);
402 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
405 // Checks if the expression is a valid reference expression (e.g., on the
406 // left-hand side of assignments). Although ruled out by ECMA as early errors,
407 // we allow calls for web compatibility and rewrite them to a runtime throw.
408 ExpressionT CheckAndRewriteReferenceExpression(
409 ExpressionT expression,
410 Scanner::Location location, const char* message, bool* ok);
412 // Used to detect duplicates in object literals. Each of the values
413 // kGetterProperty, kSetterProperty and kValueProperty represents
414 // a type of object literal property. When parsing a property, its
415 // type value is stored in the DuplicateFinder for the property name.
416 // Values are chosen so that having intersection bits means the there is
417 // an incompatibility.
418 // I.e., you can add a getter to a property that already has a setter, since
419 // kGetterProperty and kSetterProperty doesn't intersect, but not if it
420 // already has a getter or a value. Adding the getter to an existing
421 // setter will store the value (kGetterProperty | kSetterProperty), which
422 // is incompatible with adding any further properties.
425 // Bit patterns representing different object literal property types.
433 // Validation per ECMA 262 - 11.1.5 "Object Initialiser".
434 class ObjectLiteralChecker {
436 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode)
438 finder_(scanner()->unicode_cache()),
439 strict_mode_(strict_mode) { }
441 void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
444 ParserBase* parser() const { return parser_; }
445 Scanner* scanner() const { return parser_->scanner(); }
447 // Checks the type of conflict based on values coming from PropertyType.
448 bool HasConflict(PropertyKind type1, PropertyKind type2) {
449 return (type1 & type2) != 0;
451 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
452 return ((type1 & type2) & kValueFlag) != 0;
454 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
455 return ((type1 ^ type2) & kValueFlag) != 0;
457 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
458 return ((type1 | type2) & kValueFlag) == 0;
462 DuplicateFinder finder_;
463 StrictMode strict_mode_;
466 // If true, the next (and immediately following) function literal is
467 // preceded by a parenthesis.
468 // Heuristically that means that the function will be called immediately,
469 // so never lazily compile it.
470 bool parenthesized_function_;
472 typename Traits::Type::Scope* scope_; // Scope stack.
473 FunctionState* function_state_; // Function state stack.
474 v8::Extension* extension_;
475 FuncNameInferrer* fni_;
476 ParserRecorder* log_;
481 uintptr_t stack_limit_;
482 bool stack_overflow_;
485 bool allow_natives_syntax_;
486 bool allow_generators_;
489 typename Traits::Type::Zone* zone_; // Only used by Parser.
493 class PreParserIdentifier {
495 PreParserIdentifier() : type_(kUnknownIdentifier) {}
496 static PreParserIdentifier Default() {
497 return PreParserIdentifier(kUnknownIdentifier);
499 static PreParserIdentifier Eval() {
500 return PreParserIdentifier(kEvalIdentifier);
502 static PreParserIdentifier Arguments() {
503 return PreParserIdentifier(kArgumentsIdentifier);
505 static PreParserIdentifier FutureReserved() {
506 return PreParserIdentifier(kFutureReservedIdentifier);
508 static PreParserIdentifier FutureStrictReserved() {
509 return PreParserIdentifier(kFutureStrictReservedIdentifier);
511 static PreParserIdentifier Yield() {
512 return PreParserIdentifier(kYieldIdentifier);
514 bool IsEval() { return type_ == kEvalIdentifier; }
515 bool IsArguments() { return type_ == kArgumentsIdentifier; }
516 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
517 bool IsYield() { return type_ == kYieldIdentifier; }
518 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
519 bool IsFutureStrictReserved() {
520 return type_ == kFutureStrictReservedIdentifier;
522 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
527 kFutureReservedIdentifier,
528 kFutureStrictReservedIdentifier,
533 explicit PreParserIdentifier(Type type) : type_(type) {}
536 friend class PreParserExpression;
540 // Bits 0 and 1 are used to identify the type of expression:
541 // If bit 0 is set, it's an identifier.
542 // if bit 1 is set, it's a string literal.
543 // If neither is set, it's no particular type, and both set isn't
545 class PreParserExpression {
547 static PreParserExpression Default() {
548 return PreParserExpression(kUnknownExpression);
551 static PreParserExpression FromIdentifier(PreParserIdentifier id) {
552 return PreParserExpression(kIdentifierFlag |
553 (id.type_ << kIdentifierShift));
556 static PreParserExpression StringLiteral() {
557 return PreParserExpression(kUnknownStringLiteral);
560 static PreParserExpression UseStrictStringLiteral() {
561 return PreParserExpression(kUseStrictString);
564 static PreParserExpression This() {
565 return PreParserExpression(kThisExpression);
568 static PreParserExpression ThisProperty() {
569 return PreParserExpression(kThisPropertyExpression);
572 static PreParserExpression Property() {
573 return PreParserExpression(kPropertyExpression);
576 static PreParserExpression Call() {
577 return PreParserExpression(kCallExpression);
580 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
582 PreParserIdentifier AsIdentifier() {
583 ASSERT(IsIdentifier());
584 return PreParserIdentifier(
585 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
588 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
590 bool IsUseStrictLiteral() {
591 return (code_ & kStringLiteralMask) == kUseStrictString;
594 bool IsThis() { return code_ == kThisExpression; }
596 bool IsThisProperty() { return code_ == kThisPropertyExpression; }
599 return code_ == kPropertyExpression || code_ == kThisPropertyExpression;
602 bool IsCall() { return code_ == kCallExpression; }
604 bool IsValidReferenceExpression() {
605 return IsIdentifier() || IsProperty();
608 // At the moment PreParser doesn't track these expression types.
609 bool IsFunctionLiteral() const { return false; }
610 bool IsCallNew() const { return false; }
612 PreParserExpression AsFunctionLiteral() { return *this; }
614 // Dummy implementation for making expression->somefunc() work in both Parser
616 PreParserExpression* operator->() { return this; }
618 // More dummy implementations of things PreParser doesn't need to track:
619 void set_index(int index) {} // For YieldExpressions
620 void set_parenthesized() {}
623 // Least significant 2 bits are used as flags. Bits 0 and 1 represent
624 // identifiers or strings literals, and are mutually exclusive, but can both
625 // be absent. If the expression is an identifier or a string literal, the
626 // other bits describe the type (see PreParserIdentifier::Type and string
627 // literal constants below).
629 kUnknownExpression = 0,
631 kIdentifierFlag = 1, // Used to detect labels.
632 kIdentifierShift = 3,
634 kStringLiteralFlag = 2, // Used to detect directive prologue.
635 kUnknownStringLiteral = kStringLiteralFlag,
636 kUseStrictString = kStringLiteralFlag | 8,
637 kStringLiteralMask = kUseStrictString,
639 // Below here applies if neither identifier nor string literal. Reserve the
640 // 2 least significant bits for flags.
641 kThisExpression = 1 << 2,
642 kThisPropertyExpression = 2 << 2,
643 kPropertyExpression = 3 << 2,
644 kCallExpression = 4 << 2
647 explicit PreParserExpression(int expression_code) : code_(expression_code) {}
653 // PreParserExpressionList doesn't actually store the expressions because
654 // PreParser doesn't need to.
655 class PreParserExpressionList {
657 // These functions make list->Add(some_expression) work (and do nothing).
658 PreParserExpressionList() : length_(0) {}
659 PreParserExpressionList* operator->() { return this; }
660 void Add(PreParserExpression, void*) { ++length_; }
661 int length() const { return length_; }
667 class PreParserStatement {
669 static PreParserStatement Default() {
670 return PreParserStatement(kUnknownStatement);
673 static PreParserStatement FunctionDeclaration() {
674 return PreParserStatement(kFunctionDeclaration);
677 // Creates expression statement from expression.
678 // Preserves being an unparenthesized string literal, possibly
680 static PreParserStatement ExpressionStatement(
681 PreParserExpression expression) {
682 if (expression.IsUseStrictLiteral()) {
683 return PreParserStatement(kUseStrictExpressionStatement);
685 if (expression.IsStringLiteral()) {
686 return PreParserStatement(kStringLiteralExpressionStatement);
691 bool IsStringLiteral() {
692 return code_ == kStringLiteralExpressionStatement;
695 bool IsUseStrictLiteral() {
696 return code_ == kUseStrictExpressionStatement;
699 bool IsFunctionDeclaration() {
700 return code_ == kFunctionDeclaration;
706 kStringLiteralExpressionStatement,
707 kUseStrictExpressionStatement,
711 explicit PreParserStatement(Type code) : code_(code) {}
717 // PreParserStatementList doesn't actually store the statements because
718 // the PreParser does not need them.
719 class PreParserStatementList {
721 // These functions make list->Add(some_expression) work as no-ops.
722 PreParserStatementList() {}
723 PreParserStatementList* operator->() { return this; }
724 void Add(PreParserStatement, void*) {}
728 class PreParserScope {
730 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type)
731 : scope_type_(scope_type) {
732 strict_mode_ = outer_scope ? outer_scope->strict_mode() : SLOPPY;
735 ScopeType type() { return scope_type_; }
736 StrictMode strict_mode() const { return strict_mode_; }
737 void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
740 ScopeType scope_type_;
741 StrictMode strict_mode_;
745 class PreParserFactory {
747 explicit PreParserFactory(void* extra_param) {}
748 PreParserExpression NewLiteral(PreParserIdentifier identifier,
750 return PreParserExpression::Default();
752 PreParserExpression NewNumberLiteral(double number,
754 return PreParserExpression::Default();
756 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
757 PreParserIdentifier js_flags,
760 return PreParserExpression::Default();
762 PreParserExpression NewArrayLiteral(PreParserExpressionList values,
765 return PreParserExpression::Default();
767 PreParserExpression NewObjectLiteralProperty(bool is_getter,
768 PreParserExpression value,
770 return PreParserExpression::Default();
772 PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
773 PreParserExpression value) {
774 return PreParserExpression::Default();
776 PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
778 int boilerplate_properties,
781 return PreParserExpression::Default();
783 PreParserExpression NewVariableProxy(void* generator_variable) {
784 return PreParserExpression::Default();
786 PreParserExpression NewProperty(PreParserExpression obj,
787 PreParserExpression key,
790 return PreParserExpression::ThisProperty();
792 return PreParserExpression::Property();
794 PreParserExpression NewUnaryOperation(Token::Value op,
795 PreParserExpression expression,
797 return PreParserExpression::Default();
799 PreParserExpression NewBinaryOperation(Token::Value op,
800 PreParserExpression left,
801 PreParserExpression right, int pos) {
802 return PreParserExpression::Default();
804 PreParserExpression NewCompareOperation(Token::Value op,
805 PreParserExpression left,
806 PreParserExpression right, int pos) {
807 return PreParserExpression::Default();
809 PreParserExpression NewAssignment(Token::Value op,
810 PreParserExpression left,
811 PreParserExpression right,
813 return PreParserExpression::Default();
815 PreParserExpression NewYield(PreParserExpression generator_object,
816 PreParserExpression expression,
817 Yield::Kind yield_kind,
819 return PreParserExpression::Default();
821 PreParserExpression NewConditional(PreParserExpression condition,
822 PreParserExpression then_expression,
823 PreParserExpression else_expression,
825 return PreParserExpression::Default();
827 PreParserExpression NewCountOperation(Token::Value op,
829 PreParserExpression expression,
831 return PreParserExpression::Default();
833 PreParserExpression NewCall(PreParserExpression expression,
834 PreParserExpressionList arguments,
836 return PreParserExpression::Call();
838 PreParserExpression NewCallNew(PreParserExpression expression,
839 PreParserExpressionList arguments,
841 return PreParserExpression::Default();
848 class PreParserTraits {
851 // TODO(marja): To be removed. The Traits object should contain all the data
853 typedef PreParser* Parser;
855 // Used by FunctionState and BlockState.
856 typedef PreParserScope Scope;
857 // PreParser doesn't need to store generator variables.
858 typedef void GeneratorVariable;
859 // No interaction with Zones.
862 // Return types for traversing functions.
863 typedef PreParserIdentifier Identifier;
864 typedef PreParserExpression Expression;
865 typedef PreParserExpression YieldExpression;
866 typedef PreParserExpression FunctionLiteral;
867 typedef PreParserExpression ObjectLiteralProperty;
868 typedef PreParserExpression Literal;
869 typedef PreParserExpressionList ExpressionList;
870 typedef PreParserExpressionList PropertyList;
871 typedef PreParserStatementList StatementList;
873 // For constructing objects returned by the traversing functions.
874 typedef PreParserFactory Factory;
877 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
879 // Custom operations executed when FunctionStates are created and
880 // destructed. (The PreParser doesn't need to do anything.)
881 template<typename FunctionState>
882 static void SetUpFunctionState(FunctionState* function_state, void*) {}
883 template<typename FunctionState>
884 static void TearDownFunctionState(FunctionState* function_state, void*) {}
886 // Helper functions for recursive descent.
887 static bool IsEvalOrArguments(PreParserIdentifier identifier) {
888 return identifier.IsEvalOrArguments();
891 // Returns true if the expression is of type "this.foo".
892 static bool IsThisProperty(PreParserExpression expression) {
893 return expression.IsThisProperty();
896 static bool IsIdentifier(PreParserExpression expression) {
897 return expression.IsIdentifier();
900 static PreParserIdentifier AsIdentifier(PreParserExpression expression) {
901 return expression.AsIdentifier();
904 static bool IsBoilerplateProperty(PreParserExpression property) {
905 // PreParser doesn't count boilerplate properties.
909 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
913 // Functions for encapsulating the differences between parsing and preparsing;
914 // operations interleaved with the recursive descent.
915 static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
916 // PreParser should not use FuncNameInferrer.
919 static void PushPropertyName(FuncNameInferrer* fni,
920 PreParserExpression expression) {
921 // PreParser should not use FuncNameInferrer.
925 static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
926 PreParserScope* scope, PreParserExpression value, bool* has_function) {}
928 static void CheckAssigningFunctionLiteralToProperty(
929 PreParserExpression left, PreParserExpression right) {}
931 // PreParser doesn't need to keep track of eval calls.
932 static void CheckPossibleEvalCall(PreParserExpression expression,
933 PreParserScope* scope) {}
935 static PreParserExpression MarkExpressionAsLValue(
936 PreParserExpression expression) {
937 // TODO(marja): To be able to produce the same errors, the preparser needs
938 // to start tracking which expressions are variables and which are lvalues.
942 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
943 PreParserExpression y,
946 PreParserFactory* factory) {
950 PreParserExpression BuildUnaryExpression(PreParserExpression expression,
951 Token::Value op, int pos,
952 PreParserFactory* factory) {
953 return PreParserExpression::Default();
956 PreParserExpression NewThrowReferenceError(const char* type, int pos) {
957 return PreParserExpression::Default();
959 PreParserExpression NewThrowSyntaxError(
960 const char* type, Handle<Object> arg, int pos) {
961 return PreParserExpression::Default();
963 PreParserExpression NewThrowTypeError(
964 const char* type, Handle<Object> arg, int pos) {
965 return PreParserExpression::Default();
969 void ReportMessageAt(Scanner::Location location,
971 Vector<const char*> args,
972 bool is_reference_error = false);
973 void ReportMessageAt(Scanner::Location location,
975 const char* name_opt,
976 bool is_reference_error = false);
977 void ReportMessageAt(int start_pos,
980 const char* name_opt,
981 bool is_reference_error = false);
983 // "null" return type creators.
984 static PreParserIdentifier EmptyIdentifier() {
985 return PreParserIdentifier::Default();
987 static PreParserExpression EmptyExpression() {
988 return PreParserExpression::Default();
990 static PreParserExpression EmptyLiteral() {
991 return PreParserExpression::Default();
993 static PreParserExpressionList NullExpressionList() {
994 return PreParserExpressionList();
997 // Odd-ball literal creators.
998 static PreParserExpression GetLiteralTheHole(int position,
999 PreParserFactory* factory) {
1000 return PreParserExpression::Default();
1003 // Producing data during the recursive descent.
1004 PreParserIdentifier GetSymbol(Scanner* scanner);
1005 static PreParserIdentifier NextLiteralString(Scanner* scanner,
1006 PretenureFlag tenured) {
1007 return PreParserIdentifier::Default();
1010 static PreParserExpression ThisExpression(PreParserScope* scope,
1011 PreParserFactory* factory) {
1012 return PreParserExpression::This();
1015 static PreParserExpression ExpressionFromLiteral(
1016 Token::Value token, int pos, Scanner* scanner,
1017 PreParserFactory* factory) {
1018 return PreParserExpression::Default();
1021 static PreParserExpression ExpressionFromIdentifier(
1022 PreParserIdentifier name, int pos, PreParserScope* scope,
1023 PreParserFactory* factory) {
1024 return PreParserExpression::FromIdentifier(name);
1027 PreParserExpression ExpressionFromString(int pos,
1029 PreParserFactory* factory = NULL);
1031 static PreParserExpressionList NewExpressionList(int size, void* zone) {
1032 return PreParserExpressionList();
1035 static PreParserStatementList NewStatementList(int size, void* zone) {
1036 return PreParserStatementList();
1039 static PreParserExpressionList NewPropertyList(int size, void* zone) {
1040 return PreParserExpressionList();
1043 // Temporary glue; these functions will move to ParserBase.
1044 PreParserExpression ParseV8Intrinsic(bool* ok);
1045 PreParserExpression ParseFunctionLiteral(
1046 PreParserIdentifier name,
1047 Scanner::Location function_name_location,
1048 bool name_is_strict_reserved,
1050 int function_token_position,
1051 FunctionLiteral::FunctionType type,
1055 PreParser* pre_parser_;
1059 // Preparsing checks a JavaScript program and emits preparse-data that helps
1060 // a later parsing to be faster.
1061 // See preparse-data-format.h for the data format.
1063 // The PreParser checks that the syntax follows the grammar for JavaScript,
1064 // and collects some information about the program along the way.
1065 // The grammar check is only performed in order to understand the program
1066 // sufficiently to deduce some information about it, that can be used
1067 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
1068 // rather it is to speed up properly written and correct programs.
1069 // That means that contextual checks (like a label being declared where
1070 // it is used) are generally omitted.
1071 class PreParser : public ParserBase<PreParserTraits> {
1073 typedef PreParserIdentifier Identifier;
1074 typedef PreParserExpression Expression;
1075 typedef PreParserStatement Statement;
1077 enum PreParseResult {
1078 kPreParseStackOverflow,
1082 PreParser(Scanner* scanner, ParserRecorder* log, uintptr_t stack_limit)
1083 : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, NULL,
1086 // Pre-parse the program from the character stream; returns true on
1087 // success (even if parsing failed, the pre-parse data successfully
1088 // captured the syntax error), and false if a stack-overflow happened
1090 PreParseResult PreParseProgram() {
1091 PreParserScope scope(scope_, GLOBAL_SCOPE);
1092 FunctionState top_scope(&function_state_, &scope_, &scope, NULL);
1094 int start_position = scanner()->peek_location().beg_pos;
1095 ParseSourceElements(Token::EOS, &ok);
1096 if (stack_overflow()) return kPreParseStackOverflow;
1098 ReportUnexpectedToken(scanner()->current_token());
1099 } else if (scope_->strict_mode() == STRICT) {
1100 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
1102 return kPreParseSuccess;
1105 // Parses a single function literal, from the opening parentheses before
1106 // parameters to the closing brace after the body.
1107 // Returns a FunctionEntry describing the body of the function in enough
1108 // detail that it can be lazily compiled.
1109 // The scanner is expected to have matched the "function" or "function*"
1110 // keyword and parameters, and have consumed the initial '{'.
1111 // At return, unless an error occurred, the scanner is positioned before the
1113 PreParseResult PreParseLazyFunction(StrictMode strict_mode,
1115 ParserRecorder* log);
1118 friend class PreParserTraits;
1120 // These types form an algebra over syntactic categories that is just
1121 // rich enough to let us recognize and propagate the constructs that
1122 // are either being counted in the preparser data, or is important
1123 // to throw the correct syntax error exceptions.
1125 enum VariableDeclarationContext {
1131 // If a list of variable declarations includes any initializers.
1132 enum VariableDeclarationProperties {
1138 enum SourceElements {
1139 kUnknownSourceElements
1142 // All ParseXXX functions take as the last argument an *ok parameter
1143 // which is set to false if parsing failed; it is unchanged otherwise.
1144 // By making the 'exception handling' explicit, we are forced to check
1145 // for failure at the call sites.
1146 Statement ParseSourceElement(bool* ok);
1147 SourceElements ParseSourceElements(int end_token, bool* ok);
1148 Statement ParseStatement(bool* ok);
1149 Statement ParseFunctionDeclaration(bool* ok);
1150 Statement ParseBlock(bool* ok);
1151 Statement ParseVariableStatement(VariableDeclarationContext var_context,
1153 Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
1154 VariableDeclarationProperties* decl_props,
1157 Statement ParseExpressionOrLabelledStatement(bool* ok);
1158 Statement ParseIfStatement(bool* ok);
1159 Statement ParseContinueStatement(bool* ok);
1160 Statement ParseBreakStatement(bool* ok);
1161 Statement ParseReturnStatement(bool* ok);
1162 Statement ParseWithStatement(bool* ok);
1163 Statement ParseSwitchStatement(bool* ok);
1164 Statement ParseDoWhileStatement(bool* ok);
1165 Statement ParseWhileStatement(bool* ok);
1166 Statement ParseForStatement(bool* ok);
1167 Statement ParseThrowStatement(bool* ok);
1168 Statement ParseTryStatement(bool* ok);
1169 Statement ParseDebuggerStatement(bool* ok);
1170 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
1171 Expression ParseObjectLiteral(bool* ok);
1172 Expression ParseV8Intrinsic(bool* ok);
1174 Expression ParseFunctionLiteral(
1176 Scanner::Location function_name_location,
1177 bool name_is_strict_reserved,
1179 int function_token_pos,
1180 FunctionLiteral::FunctionType function_type,
1182 void ParseLazyFunctionLiteralBody(bool* ok);
1184 bool CheckInOrOf(bool accept_OF);
1187 template<class Traits>
1188 ParserBase<Traits>::FunctionState::FunctionState(
1189 FunctionState** function_state_stack,
1190 typename Traits::Type::Scope** scope_stack,
1191 typename Traits::Type::Scope* scope,
1192 typename Traits::Type::Zone* extra_param)
1193 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
1194 next_handler_index_(0),
1195 expected_property_count_(0),
1196 is_generator_(false),
1197 generator_object_variable_(NULL),
1198 function_state_stack_(function_state_stack),
1199 outer_function_state_(*function_state_stack),
1200 scope_stack_(scope_stack),
1201 outer_scope_(*scope_stack),
1202 saved_ast_node_id_(0),
1203 extra_param_(extra_param),
1204 factory_(extra_param) {
1205 *scope_stack_ = scope;
1206 *function_state_stack = this;
1207 Traits::SetUpFunctionState(this, extra_param);
1211 template<class Traits>
1212 ParserBase<Traits>::FunctionState::~FunctionState() {
1213 *scope_stack_ = outer_scope_;
1214 *function_state_stack_ = outer_function_state_;
1215 Traits::TearDownFunctionState(this, extra_param_);
1219 template<class Traits>
1220 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
1221 Scanner::Location source_location = scanner()->location();
1223 // Four of the tokens are treated specially
1226 return ReportMessageAt(source_location, "unexpected_eos");
1228 return ReportMessageAt(source_location, "unexpected_token_number");
1230 return ReportMessageAt(source_location, "unexpected_token_string");
1231 case Token::IDENTIFIER:
1232 return ReportMessageAt(source_location, "unexpected_token_identifier");
1233 case Token::FUTURE_RESERVED_WORD:
1234 return ReportMessageAt(source_location, "unexpected_reserved");
1236 case Token::FUTURE_STRICT_RESERVED_WORD:
1237 return ReportMessageAt(source_location, strict_mode() == SLOPPY
1238 ? "unexpected_token_identifier" : "unexpected_strict_reserved");
1240 const char* name = Token::String(token);
1241 ASSERT(name != NULL);
1242 Traits::ReportMessageAt(
1243 source_location, "unexpected_token", Vector<const char*>(&name, 1));
1248 template<class Traits>
1249 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
1250 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
1252 Token::Value next = Next();
1253 if (next == Token::IDENTIFIER) {
1254 IdentifierT name = this->GetSymbol(scanner());
1255 if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
1256 strict_mode() == STRICT && this->IsEvalOrArguments(name)) {
1257 ReportMessageAt(scanner()->location(), "strict_eval_arguments");
1261 } else if (strict_mode() == SLOPPY &&
1262 (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1263 (next == Token::YIELD && !is_generator()))) {
1264 return this->GetSymbol(scanner());
1266 this->ReportUnexpectedToken(next);
1268 return Traits::EmptyIdentifier();
1273 template <class Traits>
1274 typename ParserBase<Traits>::IdentifierT ParserBase<
1275 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
1277 Token::Value next = Next();
1278 if (next == Token::IDENTIFIER) {
1279 *is_strict_reserved = false;
1280 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1281 (next == Token::YIELD && !this->is_generator())) {
1282 *is_strict_reserved = true;
1284 ReportUnexpectedToken(next);
1286 return Traits::EmptyIdentifier();
1288 return this->GetSymbol(scanner());
1292 template <class Traits>
1293 typename ParserBase<Traits>::IdentifierT
1294 ParserBase<Traits>::ParseIdentifierName(bool* ok) {
1295 Token::Value next = Next();
1296 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
1297 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
1298 this->ReportUnexpectedToken(next);
1300 return Traits::EmptyIdentifier();
1302 return this->GetSymbol(scanner());
1306 template <class Traits>
1307 typename ParserBase<Traits>::IdentifierT
1308 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
1311 IdentifierT result = ParseIdentifierName(ok);
1312 if (!*ok) return Traits::EmptyIdentifier();
1313 scanner()->IsGetOrSet(is_get, is_set);
1318 template <class Traits>
1319 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
1320 bool seen_equal, bool* ok) {
1321 int pos = peek_position();
1322 if (!scanner()->ScanRegExpPattern(seen_equal)) {
1324 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
1326 return Traits::EmptyExpression();
1329 int literal_index = function_state_->NextMaterializedLiteralIndex();
1331 IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED);
1332 if (!scanner()->ScanRegExpFlags()) {
1334 ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
1336 return Traits::EmptyExpression();
1338 IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED);
1340 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
1344 #define CHECK_OK ok); \
1345 if (!*ok) return this->EmptyExpression(); \
1347 #define DUMMY ) // to make indentation work
1350 // Used in functions where the return type is not ExpressionT.
1351 #define CHECK_OK_CUSTOM(x) ok); \
1352 if (!*ok) return this->x(); \
1354 #define DUMMY ) // to make indentation work
1357 template <class Traits>
1358 typename ParserBase<Traits>::ExpressionT
1359 ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
1360 // PrimaryExpression ::
1371 // '(' Expression ')'
1373 int pos = peek_position();
1374 ExpressionT result = this->EmptyExpression();
1375 Token::Value token = peek();
1378 Consume(Token::THIS);
1379 result = this->ThisExpression(scope_, factory());
1383 case Token::NULL_LITERAL:
1384 case Token::TRUE_LITERAL:
1385 case Token::FALSE_LITERAL:
1388 result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
1391 case Token::IDENTIFIER:
1393 case Token::FUTURE_STRICT_RESERVED_WORD: {
1394 // Using eval or arguments in this context is OK even in strict mode.
1395 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1396 result = this->ExpressionFromIdentifier(name, pos, scope_, factory());
1400 case Token::STRING: {
1401 Consume(Token::STRING);
1402 result = this->ExpressionFromString(pos, scanner(), factory());
1406 case Token::ASSIGN_DIV:
1407 result = this->ParseRegExpLiteral(true, CHECK_OK);
1411 result = this->ParseRegExpLiteral(false, CHECK_OK);
1415 result = this->ParseArrayLiteral(CHECK_OK);
1419 result = this->ParseObjectLiteral(CHECK_OK);
1423 Consume(Token::LPAREN);
1424 // Heuristically try to detect immediately called functions before
1425 // seeing the call parentheses.
1426 parenthesized_function_ = (peek() == Token::FUNCTION);
1427 result = this->ParseExpression(true, CHECK_OK);
1428 Expect(Token::RPAREN, CHECK_OK);
1432 if (allow_natives_syntax() || extension_ != NULL) {
1433 result = this->ParseV8Intrinsic(CHECK_OK);
1436 // If we're not allowing special syntax we fall-through to the
1441 ReportUnexpectedToken(token);
1450 template <class Traits>
1451 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
1452 bool accept_IN, bool* ok) {
1454 // AssignmentExpression
1455 // Expression ',' AssignmentExpression
1457 ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1458 while (peek() == Token::COMMA) {
1459 Expect(Token::COMMA, CHECK_OK);
1460 int pos = position();
1461 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1462 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
1468 template <class Traits>
1469 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
1472 // '[' Expression? (',' Expression?)* ']'
1474 int pos = peek_position();
1475 typename Traits::Type::ExpressionList values =
1476 this->NewExpressionList(4, zone_);
1477 Expect(Token::LBRACK, CHECK_OK);
1478 while (peek() != Token::RBRACK) {
1479 ExpressionT elem = this->EmptyExpression();
1480 if (peek() == Token::COMMA) {
1481 elem = this->GetLiteralTheHole(peek_position(), factory());
1483 elem = this->ParseAssignmentExpression(true, CHECK_OK);
1485 values->Add(elem, zone_);
1486 if (peek() != Token::RBRACK) {
1487 Expect(Token::COMMA, CHECK_OK);
1490 Expect(Token::RBRACK, CHECK_OK);
1492 // Update the scope information before the pre-parsing bailout.
1493 int literal_index = function_state_->NextMaterializedLiteralIndex();
1495 return factory()->NewArrayLiteral(values, literal_index, pos);
1499 template <class Traits>
1500 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
1504 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
1505 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1507 // (Except that trailing comma is not required and not allowed.)
1509 int pos = peek_position();
1510 typename Traits::Type::PropertyList properties =
1511 this->NewPropertyList(4, zone_);
1512 int number_of_boilerplate_properties = 0;
1513 bool has_function = false;
1515 ObjectLiteralChecker checker(this, strict_mode());
1517 Expect(Token::LBRACE, CHECK_OK);
1519 while (peek() != Token::RBRACE) {
1520 if (fni_ != NULL) fni_->Enter();
1522 typename Traits::Type::Literal key = this->EmptyLiteral();
1523 Token::Value next = peek();
1524 int next_pos = peek_position();
1527 case Token::FUTURE_RESERVED_WORD:
1528 case Token::FUTURE_STRICT_RESERVED_WORD:
1529 case Token::IDENTIFIER: {
1530 bool is_getter = false;
1531 bool is_setter = false;
1533 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1534 if (fni_ != NULL) this->PushLiteralName(fni_, id);
1536 if ((is_getter || is_setter) && peek() != Token::COLON) {
1537 // Special handling of getter and setter syntax:
1538 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
1539 // We have already read the "get" or "set" keyword.
1540 Token::Value next = Next();
1541 if (next != i::Token::IDENTIFIER &&
1542 next != i::Token::FUTURE_RESERVED_WORD &&
1543 next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1544 next != i::Token::NUMBER &&
1545 next != i::Token::STRING &&
1546 !Token::IsKeyword(next)) {
1547 ReportUnexpectedToken(next);
1549 return this->EmptyLiteral();
1551 // Validate the property.
1552 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
1553 checker.CheckProperty(next, type, CHECK_OK);
1554 IdentifierT name = this->GetSymbol(scanner_);
1555 typename Traits::Type::FunctionLiteral value =
1556 this->ParseFunctionLiteral(
1557 name, scanner()->location(),
1558 false, // reserved words are allowed here
1559 false, // not a generator
1560 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
1562 // Allow any number of parameters for compatibilty with JSC.
1563 // Specification only allows zero parameters for get and one for set.
1564 typename Traits::Type::ObjectLiteralProperty property =
1565 factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
1566 if (this->IsBoilerplateProperty(property)) {
1567 number_of_boilerplate_properties++;
1569 properties->Add(property, zone());
1570 if (peek() != Token::RBRACE) {
1571 // Need {} because of the CHECK_OK macro.
1572 Expect(Token::COMMA, CHECK_OK);
1579 continue; // restart the while
1581 // Failed to parse as get/set property, so it's just a normal property
1582 // (which might be called "get" or "set" or something else).
1583 key = factory()->NewLiteral(id, next_pos);
1586 case Token::STRING: {
1587 Consume(Token::STRING);
1588 IdentifierT string = this->GetSymbol(scanner_);
1589 if (fni_ != NULL) this->PushLiteralName(fni_, string);
1591 if (this->IsArrayIndex(string, &index)) {
1592 key = factory()->NewNumberLiteral(index, next_pos);
1595 key = factory()->NewLiteral(string, next_pos);
1598 case Token::NUMBER: {
1599 Consume(Token::NUMBER);
1600 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
1605 if (Token::IsKeyword(next)) {
1607 IdentifierT string = this->GetSymbol(scanner_);
1608 key = factory()->NewLiteral(string, next_pos);
1610 Token::Value next = Next();
1611 ReportUnexpectedToken(next);
1613 return this->EmptyLiteral();
1617 // Validate the property
1618 checker.CheckProperty(next, kValueProperty, CHECK_OK);
1620 Expect(Token::COLON, CHECK_OK);
1621 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK);
1623 typename Traits::Type::ObjectLiteralProperty property =
1624 factory()->NewObjectLiteralProperty(key, value);
1626 // Mark top-level object literals that contain function literals and
1627 // pretenure the literal so it can be added as a constant function
1628 // property. (Parser only.)
1629 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value,
1632 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
1633 if (this->IsBoilerplateProperty(property)) {
1634 number_of_boilerplate_properties++;
1636 properties->Add(property, zone());
1638 // TODO(1240767): Consider allowing trailing comma.
1639 if (peek() != Token::RBRACE) {
1640 // Need {} because of the CHECK_OK macro.
1641 Expect(Token::COMMA, CHECK_OK);
1649 Expect(Token::RBRACE, CHECK_OK);
1651 // Computation of literal_index must happen before pre parse bailout.
1652 int literal_index = function_state_->NextMaterializedLiteralIndex();
1654 return factory()->NewObjectLiteral(properties,
1656 number_of_boilerplate_properties,
1662 template <class Traits>
1663 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
1666 // '(' (AssignmentExpression)*[','] ')'
1668 typename Traits::Type::ExpressionList result =
1669 this->NewExpressionList(4, zone_);
1670 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
1671 bool done = (peek() == Token::RPAREN);
1673 ExpressionT argument = this->ParseAssignmentExpression(
1674 true, CHECK_OK_CUSTOM(NullExpressionList));
1675 result->Add(argument, zone_);
1676 if (result->length() > Code::kMaxArguments) {
1677 ReportMessageAt(scanner()->location(), "too_many_arguments");
1679 return this->NullExpressionList();
1681 done = (peek() == Token::RPAREN);
1683 // Need {} because of the CHECK_OK_CUSTOM macro.
1684 Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList));
1687 Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
1692 template <class Traits>
1693 typename ParserBase<Traits>::ExpressionT
1694 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
1695 // AssignmentExpression ::
1696 // ConditionalExpression
1698 // LeftHandSideExpression AssignmentOperator AssignmentExpression
1700 Scanner::Location lhs_location = scanner()->peek_location();
1702 if (peek() == Token::YIELD && is_generator()) {
1703 return this->ParseYieldExpression(ok);
1706 if (fni_ != NULL) fni_->Enter();
1707 ExpressionT expression =
1708 this->ParseConditionalExpression(accept_IN, CHECK_OK);
1710 if (!Token::IsAssignmentOp(peek())) {
1711 if (fni_ != NULL) fni_->Leave();
1712 // Parsed conditional expression only (no assignment).
1716 expression = this->CheckAndRewriteReferenceExpression(
1717 expression, lhs_location, "invalid_lhs_in_assignment", CHECK_OK);
1718 expression = this->MarkExpressionAsLValue(expression);
1720 Token::Value op = Next(); // Get assignment operator.
1721 int pos = position();
1722 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1724 // TODO(1231235): We try to estimate the set of properties set by
1725 // constructors. We define a new property whenever there is an
1726 // assignment to a property of 'this'. We should probably only add
1727 // properties if we haven't seen them before. Otherwise we'll
1728 // probably overestimate the number of properties.
1729 if (op == Token::ASSIGN && this->IsThisProperty(expression)) {
1730 function_state_->AddProperty();
1733 this->CheckAssigningFunctionLiteralToProperty(expression, right);
1736 // Check if the right hand side is a call to avoid inferring a
1737 // name if we're dealing with "a = function(){...}();"-like
1739 if ((op == Token::INIT_VAR
1740 || op == Token::INIT_CONST_LEGACY
1741 || op == Token::ASSIGN)
1742 && (!right->IsCall() && !right->IsCallNew())) {
1745 fni_->RemoveLastFunction();
1750 return factory()->NewAssignment(op, expression, right, pos);
1753 template <class Traits>
1754 typename ParserBase<Traits>::ExpressionT
1755 ParserBase<Traits>::ParseYieldExpression(bool* ok) {
1756 // YieldExpression ::
1757 // 'yield' '*'? AssignmentExpression
1758 int pos = peek_position();
1759 Expect(Token::YIELD, CHECK_OK);
1761 Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
1762 ExpressionT generator_object =
1763 factory()->NewVariableProxy(function_state_->generator_object_variable());
1764 ExpressionT expression =
1765 ParseAssignmentExpression(false, CHECK_OK);
1766 typename Traits::Type::YieldExpression yield =
1767 factory()->NewYield(generator_object, expression, kind, pos);
1768 if (kind == Yield::DELEGATING) {
1769 yield->set_index(function_state_->NextHandlerIndex());
1776 template <class Traits>
1777 typename ParserBase<Traits>::ExpressionT
1778 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
1779 // ConditionalExpression ::
1780 // LogicalOrExpression
1781 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
1783 int pos = peek_position();
1784 // We start using the binary expression parser for prec >= 4 only!
1785 ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK);
1786 if (peek() != Token::CONDITIONAL) return expression;
1787 Consume(Token::CONDITIONAL);
1788 // In parsing the first assignment expression in conditional
1789 // expressions we always accept the 'in' keyword; see ECMA-262,
1790 // section 11.12, page 58.
1791 ExpressionT left = ParseAssignmentExpression(true, CHECK_OK);
1792 Expect(Token::COLON, CHECK_OK);
1793 ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK);
1794 return factory()->NewConditional(expression, left, right, pos);
1799 template <class Traits>
1800 typename ParserBase<Traits>::ExpressionT
1801 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
1803 ExpressionT x = this->ParseUnaryExpression(CHECK_OK);
1804 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
1806 while (Precedence(peek(), accept_IN) == prec1) {
1807 Token::Value op = Next();
1808 int pos = position();
1809 ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
1811 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
1816 // For now we distinguish between comparisons and other binary
1817 // operations. (We could combine the two and get rid of this
1818 // code and AST node eventually.)
1819 if (Token::IsCompareOp(op)) {
1820 // We have a comparison.
1821 Token::Value cmp = op;
1823 case Token::NE: cmp = Token::EQ; break;
1824 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
1827 x = factory()->NewCompareOperation(cmp, x, y, pos);
1829 // The comparison was negated - add a NOT.
1830 x = factory()->NewUnaryOperation(Token::NOT, x, pos);
1834 // We have a "normal" binary operation.
1835 x = factory()->NewBinaryOperation(op, x, y, pos);
1843 template <class Traits>
1844 typename ParserBase<Traits>::ExpressionT
1845 ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
1846 // UnaryExpression ::
1847 // PostfixExpression
1848 // 'delete' UnaryExpression
1849 // 'void' UnaryExpression
1850 // 'typeof' UnaryExpression
1851 // '++' UnaryExpression
1852 // '--' UnaryExpression
1853 // '+' UnaryExpression
1854 // '-' UnaryExpression
1855 // '~' UnaryExpression
1856 // '!' UnaryExpression
1858 Token::Value op = peek();
1859 if (Token::IsUnaryOp(op)) {
1861 int pos = position();
1862 ExpressionT expression = ParseUnaryExpression(CHECK_OK);
1864 // "delete identifier" is a syntax error in strict mode.
1865 if (op == Token::DELETE && strict_mode() == STRICT &&
1866 this->IsIdentifier(expression)) {
1867 ReportMessage("strict_delete", Vector<const char*>::empty());
1869 return this->EmptyExpression();
1872 // Allow Traits do rewrite the expression.
1873 return this->BuildUnaryExpression(expression, op, pos, factory());
1874 } else if (Token::IsCountOp(op)) {
1876 Scanner::Location lhs_location = scanner()->peek_location();
1877 ExpressionT expression = this->ParseUnaryExpression(CHECK_OK);
1878 expression = this->CheckAndRewriteReferenceExpression(
1879 expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK);
1880 this->MarkExpressionAsLValue(expression);
1882 return factory()->NewCountOperation(op,
1888 return this->ParsePostfixExpression(ok);
1893 template <class Traits>
1894 typename ParserBase<Traits>::ExpressionT
1895 ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
1896 // PostfixExpression ::
1897 // LeftHandSideExpression ('++' | '--')?
1899 Scanner::Location lhs_location = scanner()->peek_location();
1900 ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK);
1901 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
1902 Token::IsCountOp(peek())) {
1903 expression = this->CheckAndRewriteReferenceExpression(
1904 expression, lhs_location, "invalid_lhs_in_postfix_op", CHECK_OK);
1905 expression = this->MarkExpressionAsLValue(expression);
1907 Token::Value next = Next();
1909 factory()->NewCountOperation(next,
1910 false /* postfix */,
1918 template <class Traits>
1919 typename ParserBase<Traits>::ExpressionT
1920 ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
1921 // LeftHandSideExpression ::
1922 // (NewExpression | MemberExpression) ...
1924 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
1928 case Token::LBRACK: {
1929 Consume(Token::LBRACK);
1930 int pos = position();
1931 ExpressionT index = ParseExpression(true, CHECK_OK);
1932 result = factory()->NewProperty(result, index, pos);
1933 Expect(Token::RBRACK, CHECK_OK);
1937 case Token::LPAREN: {
1939 if (scanner()->current_token() == Token::IDENTIFIER) {
1940 // For call of an identifier we want to report position of
1941 // the identifier as position of the call in the stack trace.
1944 // For other kinds of calls we record position of the parenthesis as
1945 // position of the call. Note that this is extremely important for
1946 // expressions of the form function(){...}() for which call position
1947 // should not point to the closing brace otherwise it will intersect
1948 // with positions recorded for function literal and confuse debugger.
1949 pos = peek_position();
1950 // Also the trailing parenthesis are a hint that the function will
1951 // be called immediately. If we happen to have parsed a preceding
1952 // function literal eagerly, we can also compile it eagerly.
1953 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
1954 result->AsFunctionLiteral()->set_parenthesized();
1957 typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK);
1959 // Keep track of eval() calls since they disable all local variable
1961 // The calls that need special treatment are the
1962 // direct eval calls. These calls are all of the form eval(...), with
1963 // no explicit receiver.
1964 // These calls are marked as potentially direct eval calls. Whether
1965 // they are actually direct calls to eval is determined at run time.
1966 this->CheckPossibleEvalCall(result, scope_);
1967 result = factory()->NewCall(result, args, pos);
1968 if (fni_ != NULL) fni_->RemoveLastFunction();
1972 case Token::PERIOD: {
1973 Consume(Token::PERIOD);
1974 int pos = position();
1975 IdentifierT name = ParseIdentifierName(CHECK_OK);
1976 result = factory()->NewProperty(
1977 result, factory()->NewLiteral(name, pos), pos);
1978 if (fni_ != NULL) this->PushLiteralName(fni_, name);
1989 template <class Traits>
1990 typename ParserBase<Traits>::ExpressionT
1991 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
1993 // ('new')+ MemberExpression
1995 // The grammar for new expressions is pretty warped. We can have several 'new'
1996 // keywords following each other, and then a MemberExpression. When we see '('
1997 // after the MemberExpression, it's associated with the rightmost unassociated
1998 // 'new' to create a NewExpression with arguments. However, a NewExpression
1999 // can also occur without arguments.
2001 // Examples of new expression:
2002 // new foo.bar().baz means (new (foo.bar)()).baz
2003 // new foo()() means (new foo())()
2004 // new new foo()() means (new (new foo())())
2005 // new new foo means new (new foo)
2006 // new new foo() means new (new foo())
2007 // new new foo().bar().baz means (new (new foo()).bar()).baz
2009 if (peek() == Token::NEW) {
2010 Consume(Token::NEW);
2011 int new_pos = position();
2012 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
2013 if (peek() == Token::LPAREN) {
2014 // NewExpression with arguments.
2015 typename Traits::Type::ExpressionList args =
2016 this->ParseArguments(CHECK_OK);
2017 result = factory()->NewCallNew(result, args, new_pos);
2018 // The expression can still continue with . or [ after the arguments.
2019 result = this->ParseMemberExpressionContinuation(result, CHECK_OK);
2022 // NewExpression without arguments.
2023 return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
2026 // No 'new' keyword.
2027 return this->ParseMemberExpression(ok);
2031 template <class Traits>
2032 typename ParserBase<Traits>::ExpressionT
2033 ParserBase<Traits>::ParseMemberExpression(bool* ok) {
2034 // MemberExpression ::
2035 // (PrimaryExpression | FunctionLiteral)
2036 // ('[' Expression ']' | '.' Identifier | Arguments)*
2038 // The '[' Expression ']' and '.' Identifier parts are parsed by
2039 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
2042 // Parse the initial primary or function expression.
2043 ExpressionT result = this->EmptyExpression();
2044 if (peek() == Token::FUNCTION) {
2045 Consume(Token::FUNCTION);
2046 int function_token_position = position();
2047 bool is_generator = allow_generators() && Check(Token::MUL);
2048 IdentifierT name = this->EmptyIdentifier();
2049 bool is_strict_reserved_name = false;
2050 Scanner::Location function_name_location = Scanner::Location::invalid();
2051 FunctionLiteral::FunctionType function_type =
2052 FunctionLiteral::ANONYMOUS_EXPRESSION;
2053 if (peek_any_identifier()) {
2054 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
2056 function_name_location = scanner()->location();
2057 function_type = FunctionLiteral::NAMED_EXPRESSION;
2059 result = this->ParseFunctionLiteral(name,
2060 function_name_location,
2061 is_strict_reserved_name,
2063 function_token_position,
2067 result = ParsePrimaryExpression(CHECK_OK);
2070 result = ParseMemberExpressionContinuation(result, CHECK_OK);
2075 template <class Traits>
2076 typename ParserBase<Traits>::ExpressionT
2077 ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
2079 // Parses this part of MemberExpression:
2080 // ('[' Expression ']' | '.' Identifier)*
2083 case Token::LBRACK: {
2084 Consume(Token::LBRACK);
2085 int pos = position();
2086 ExpressionT index = this->ParseExpression(true, CHECK_OK);
2087 expression = factory()->NewProperty(expression, index, pos);
2089 this->PushPropertyName(fni_, index);
2091 Expect(Token::RBRACK, CHECK_OK);
2094 case Token::PERIOD: {
2095 Consume(Token::PERIOD);
2096 int pos = position();
2097 IdentifierT name = ParseIdentifierName(CHECK_OK);
2098 expression = factory()->NewProperty(
2099 expression, factory()->NewLiteral(name, pos), pos);
2101 this->PushLiteralName(fni_, name);
2110 return this->EmptyExpression();
2114 template <typename Traits>
2115 typename ParserBase<Traits>::ExpressionT
2116 ParserBase<Traits>::CheckAndRewriteReferenceExpression(
2117 ExpressionT expression,
2118 Scanner::Location location, const char* message, bool* ok) {
2119 if (strict_mode() == STRICT && this->IsIdentifier(expression) &&
2120 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
2121 this->ReportMessageAt(location, "strict_eval_arguments", false);
2123 return this->EmptyExpression();
2124 } else if (expression->IsValidReferenceExpression()) {
2126 } else if (expression->IsCall()) {
2127 // If it is a call, make it a runtime error for legacy web compatibility.
2128 // Rewrite `expr' to `expr[throw ReferenceError]'.
2129 int pos = location.beg_pos;
2130 ExpressionT error = this->NewThrowReferenceError(message, pos);
2131 return factory()->NewProperty(expression, error, pos);
2133 this->ReportMessageAt(location, message, true);
2135 return this->EmptyExpression();
2141 #undef CHECK_OK_CUSTOM
2144 template <typename Traits>
2145 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
2146 Token::Value property,
2150 if (property == Token::NUMBER) {
2151 old = scanner()->FindNumber(&finder_, type);
2153 old = scanner()->FindSymbol(&finder_, type);
2155 PropertyKind old_type = static_cast<PropertyKind>(old);
2156 if (HasConflict(old_type, type)) {
2157 if (IsDataDataConflict(old_type, type)) {
2158 // Both are data properties.
2159 if (strict_mode_ == SLOPPY) return;
2160 parser()->ReportMessageAt(scanner()->location(),
2161 "strict_duplicate_property");
2162 } else if (IsDataAccessorConflict(old_type, type)) {
2163 // Both a data and an accessor property with the same name.
2164 parser()->ReportMessageAt(scanner()->location(),
2165 "accessor_data_property");
2167 ASSERT(IsAccessorAccessorConflict(old_type, type));
2168 // Both accessors of the same type.
2169 parser()->ReportMessageAt(scanner()->location(),
2170 "accessor_get_set");
2179 #endif // V8_PREPARSER_H