1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifndef V8_PREPARSER_H
29 #define V8_PREPARSER_H
31 #include "func-name-inferrer.h"
41 // Common base class shared between parser and pre-parser. Traits encapsulate
42 // the differences between Parser and PreParser:
44 // - Return types: For example, Parser functions return Expression* and
45 // PreParser functions return PreParserExpression.
47 // - Creating parse tree nodes: Parser generates an AST during the recursive
48 // descent. PreParser doesn't create a tree. Instead, it passes around minimal
49 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain
50 // just enough data for the upper layer functions. PreParserFactory is
51 // responsible for creating these dummy objects. It provides a similar kind of
52 // interface as AstNodeFactory, so ParserBase doesn't need to care which one is
55 // - Miscellanous other tasks interleaved with the recursive descent. For
56 // example, Parser keeps track of which function literals should be marked as
57 // pretenured, and PreParser doesn't care.
59 // The traits are expected to contain the following typedefs:
61 // // In particular...
63 // // Used by FunctionState and BlockState.
65 // typedef GeneratorVariable;
67 // // Return types for traversing functions.
68 // typedef Identifier;
69 // typedef Expression;
70 // typedef FunctionLiteral;
71 // typedef ObjectLiteralProperty;
73 // typedef ExpressionList;
74 // typedef PropertyList;
75 // // For constructing objects returned by the traversing functions.
81 template <typename Traits>
82 class ParserBase : public Traits {
84 // Shorten type names defined by Traits.
85 typedef typename Traits::Type::Expression ExpressionT;
86 typedef typename Traits::Type::Identifier IdentifierT;
88 ParserBase(Scanner* scanner, uintptr_t stack_limit,
89 v8::Extension* extension,
91 typename Traits::Type::Zone* zone,
92 typename Traits::Type::Parser this_object)
93 : Traits(this_object),
94 parenthesized_function_(false),
96 function_state_(NULL),
97 extension_(extension),
100 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
102 stack_limit_(stack_limit),
103 stack_overflow_(false),
105 allow_natives_syntax_(false),
106 allow_generators_(false),
107 allow_for_of_(false),
110 // Getters that indicate whether certain syntactical constructs are
111 // allowed to be parsed by this instance of the parser.
112 bool allow_lazy() const { return allow_lazy_; }
113 bool allow_natives_syntax() const { return allow_natives_syntax_; }
114 bool allow_generators() const { return allow_generators_; }
115 bool allow_for_of() const { return allow_for_of_; }
116 bool allow_modules() const { return scanner()->HarmonyModules(); }
117 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
118 bool allow_harmony_numeric_literals() const {
119 return scanner()->HarmonyNumericLiterals();
122 // Setters that determine whether certain syntactical constructs are
123 // allowed to be parsed by this instance of the parser.
124 void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
125 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
126 void set_allow_generators(bool allow) { allow_generators_ = allow; }
127 void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
128 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
129 void set_allow_harmony_scoping(bool allow) {
130 scanner()->SetHarmonyScoping(allow);
132 void set_allow_harmony_numeric_literals(bool allow) {
133 scanner()->SetHarmonyNumericLiterals(allow);
137 enum AllowEvalOrArgumentsAsIdentifier {
138 kAllowEvalOrArguments,
139 kDontAllowEvalOrArguments
147 // ---------------------------------------------------------------------------
148 // FunctionState and BlockState together implement the parser's scope stack.
149 // The parser's current scope is in scope_. BlockState and FunctionState
150 // constructors push on the scope stack and the destructors pop. They are also
151 // used to hold the parser's per-function and per-block state.
152 class BlockState BASE_EMBEDDED {
154 BlockState(typename Traits::Type::Scope** scope_stack,
155 typename Traits::Type::Scope* scope)
156 : scope_stack_(scope_stack),
157 outer_scope_(*scope_stack),
159 *scope_stack_ = scope_;
161 ~BlockState() { *scope_stack_ = outer_scope_; }
164 typename Traits::Type::Scope** scope_stack_;
165 typename Traits::Type::Scope* outer_scope_;
166 typename Traits::Type::Scope* scope_;
169 class FunctionState BASE_EMBEDDED {
172 FunctionState** function_state_stack,
173 typename Traits::Type::Scope** scope_stack,
174 typename Traits::Type::Scope* scope,
175 typename Traits::Type::Zone* zone = NULL);
178 int NextMaterializedLiteralIndex() {
179 return next_materialized_literal_index_++;
181 int materialized_literal_count() {
182 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
185 int NextHandlerIndex() { return next_handler_index_++; }
186 int handler_count() { return next_handler_index_; }
188 void AddProperty() { expected_property_count_++; }
189 int expected_property_count() { return expected_property_count_; }
191 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
192 bool is_generator() const { return is_generator_; }
194 void set_generator_object_variable(
195 typename Traits::Type::GeneratorVariable* variable) {
196 ASSERT(variable != NULL);
197 ASSERT(!is_generator());
198 generator_object_variable_ = variable;
199 is_generator_ = true;
201 typename Traits::Type::GeneratorVariable* generator_object_variable()
203 return generator_object_variable_;
206 typename Traits::Type::Factory* factory() { return &factory_; }
209 // Used to assign an index to each literal that needs materialization in
210 // the function. Includes regexp literals, and boilerplate for object and
212 int next_materialized_literal_index_;
214 // Used to assign a per-function index to try and catch handlers.
215 int next_handler_index_;
217 // Properties count estimation.
218 int expected_property_count_;
220 // Whether the function is a generator.
222 // For generators, this variable may hold the generator object. It variable
223 // is used by yield expressions and return statements. It is not necessary
224 // for generator functions to have this variable set.
225 Variable* generator_object_variable_;
227 FunctionState** function_state_stack_;
228 FunctionState* outer_function_state_;
229 typename Traits::Type::Scope** scope_stack_;
230 typename Traits::Type::Scope* outer_scope_;
231 Isolate* isolate_; // Only used by ParserTraits.
232 int saved_ast_node_id_; // Only used by ParserTraits.
233 typename Traits::Type::Factory factory_;
235 friend class ParserTraits;
238 class ParsingModeScope BASE_EMBEDDED {
240 ParsingModeScope(ParserBase* parser, Mode mode)
242 old_mode_(parser->mode()) {
243 parser_->mode_ = mode;
245 ~ParsingModeScope() {
246 parser_->mode_ = old_mode_;
254 Scanner* scanner() const { return scanner_; }
255 int position() { return scanner_->location().beg_pos; }
256 int peek_position() { return scanner_->peek_location().beg_pos; }
257 bool stack_overflow() const { return stack_overflow_; }
258 void set_stack_overflow() { stack_overflow_ = true; }
259 Mode mode() const { return mode_; }
260 typename Traits::Type::Zone* zone() const { return zone_; }
262 INLINE(Token::Value peek()) {
263 if (stack_overflow_) return Token::ILLEGAL;
264 return scanner()->peek();
267 INLINE(Token::Value Next()) {
268 if (stack_overflow_) return Token::ILLEGAL;
271 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
272 // Any further calls to Next or peek will return the illegal token.
273 // The current call must return the next token, which might already
274 // have been peek'ed.
275 stack_overflow_ = true;
278 return scanner()->Next();
281 void Consume(Token::Value token) {
282 Token::Value next = Next();
285 ASSERT(next == token);
288 bool Check(Token::Value token) {
289 Token::Value next = peek();
297 void Expect(Token::Value token, bool* ok) {
298 Token::Value next = Next();
300 ReportUnexpectedToken(next);
305 void ExpectSemicolon(bool* ok) {
306 // Check for automatic semicolon insertion according to
307 // the rules given in ECMA-262, section 7.9, page 21.
308 Token::Value tok = peek();
309 if (tok == Token::SEMICOLON) {
313 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
314 tok == Token::RBRACE ||
318 Expect(Token::SEMICOLON, ok);
321 bool peek_any_identifier() {
322 Token::Value next = peek();
323 return next == Token::IDENTIFIER ||
324 next == Token::FUTURE_RESERVED_WORD ||
325 next == Token::FUTURE_STRICT_RESERVED_WORD ||
326 next == Token::YIELD;
329 bool CheckContextualKeyword(Vector<const char> keyword) {
330 if (peek() == Token::IDENTIFIER &&
331 scanner()->is_next_contextual_keyword(keyword)) {
332 Consume(Token::IDENTIFIER);
338 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
339 Expect(Token::IDENTIFIER, ok);
341 if (!scanner()->is_literal_contextual_keyword(keyword)) {
342 ReportUnexpectedToken(scanner()->current_token());
347 // Checks whether an octal literal was last seen between beg_pos and end_pos.
348 // If so, reports an error. Only called for strict mode.
349 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
350 Scanner::Location octal = scanner()->octal_position();
351 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
352 octal.end_pos <= end_pos) {
353 ReportMessageAt(octal, "strict_octal_literal");
354 scanner()->clear_octal_position();
359 // Determine precedence of given token.
360 static int Precedence(Token::Value token, bool accept_IN) {
361 if (token == Token::IN && !accept_IN)
362 return 0; // 0 precedence will terminate binary expression parsing
363 return Token::Precedence(token);
366 typename Traits::Type::Factory* factory() {
367 return function_state_->factory();
370 StrictMode strict_mode() { return scope_->strict_mode(); }
371 bool is_generator() const { return function_state_->is_generator(); }
373 // Report syntax errors.
374 void ReportMessage(const char* message, Vector<const char*> args,
375 bool is_reference_error = false) {
376 Scanner::Location source_location = scanner()->location();
377 Traits::ReportMessageAt(source_location, message, args, is_reference_error);
380 void ReportMessageAt(Scanner::Location location, const char* message,
381 bool is_reference_error = false) {
382 Traits::ReportMessageAt(location, message, Vector<const char*>::empty(),
386 void ReportUnexpectedToken(Token::Value token);
388 // Recursive descent functions:
390 // Parses an identifier that is valid for the current scope, in particular it
391 // fails on strict mode future reserved keywords in a strict scope. If
392 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
393 // "arguments" as identifier even in strict mode (this is needed in cases like
394 // "var foo = eval;").
395 IdentifierT ParseIdentifier(
396 AllowEvalOrArgumentsAsIdentifier,
398 // Parses an identifier or a strict mode future reserved word, and indicate
399 // whether it is strict mode future reserved.
400 IdentifierT ParseIdentifierOrStrictReservedWord(
401 bool* is_strict_reserved,
403 IdentifierT ParseIdentifierName(bool* ok);
404 // Parses an identifier and determines whether or not it is 'get' or 'set'.
405 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get,
409 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok);
411 ExpressionT ParsePrimaryExpression(bool* ok);
412 ExpressionT ParseExpression(bool accept_IN, bool* ok);
413 ExpressionT ParseArrayLiteral(bool* ok);
414 ExpressionT ParseObjectLiteral(bool* ok);
415 typename Traits::Type::ExpressionList ParseArguments(bool* ok);
416 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
417 ExpressionT ParseYieldExpression(bool* ok);
418 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
419 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
420 ExpressionT ParseUnaryExpression(bool* ok);
421 ExpressionT ParsePostfixExpression(bool* ok);
422 ExpressionT ParseLeftHandSideExpression(bool* ok);
423 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
424 ExpressionT ParseMemberExpression(bool* ok);
425 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
428 // Used to detect duplicates in object literals. Each of the values
429 // kGetterProperty, kSetterProperty and kValueProperty represents
430 // a type of object literal property. When parsing a property, its
431 // type value is stored in the DuplicateFinder for the property name.
432 // Values are chosen so that having intersection bits means the there is
433 // an incompatibility.
434 // I.e., you can add a getter to a property that already has a setter, since
435 // kGetterProperty and kSetterProperty doesn't intersect, but not if it
436 // already has a getter or a value. Adding the getter to an existing
437 // setter will store the value (kGetterProperty | kSetterProperty), which
438 // is incompatible with adding any further properties.
441 // Bit patterns representing different object literal property types.
449 // Validation per ECMA 262 - 11.1.5 "Object Initialiser".
450 class ObjectLiteralChecker {
452 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode)
454 finder_(scanner()->unicode_cache()),
455 strict_mode_(strict_mode) { }
457 void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
460 ParserBase* parser() const { return parser_; }
461 Scanner* scanner() const { return parser_->scanner(); }
463 // Checks the type of conflict based on values coming from PropertyType.
464 bool HasConflict(PropertyKind type1, PropertyKind type2) {
465 return (type1 & type2) != 0;
467 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
468 return ((type1 & type2) & kValueFlag) != 0;
470 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
471 return ((type1 ^ type2) & kValueFlag) != 0;
473 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
474 return ((type1 | type2) & kValueFlag) == 0;
478 DuplicateFinder finder_;
479 StrictMode strict_mode_;
482 // If true, the next (and immediately following) function literal is
483 // preceded by a parenthesis.
484 // Heuristically that means that the function will be called immediately,
485 // so never lazily compile it.
486 bool parenthesized_function_;
488 typename Traits::Type::Scope* scope_; // Scope stack.
489 FunctionState* function_state_; // Function state stack.
490 v8::Extension* extension_;
491 FuncNameInferrer* fni_;
492 ParserRecorder* log_;
497 uintptr_t stack_limit_;
498 bool stack_overflow_;
501 bool allow_natives_syntax_;
502 bool allow_generators_;
505 typename Traits::Type::Zone* zone_; // Only used by Parser.
509 class PreParserIdentifier {
511 PreParserIdentifier() : type_(kUnknownIdentifier) {}
512 static PreParserIdentifier Default() {
513 return PreParserIdentifier(kUnknownIdentifier);
515 static PreParserIdentifier Eval() {
516 return PreParserIdentifier(kEvalIdentifier);
518 static PreParserIdentifier Arguments() {
519 return PreParserIdentifier(kArgumentsIdentifier);
521 static PreParserIdentifier FutureReserved() {
522 return PreParserIdentifier(kFutureReservedIdentifier);
524 static PreParserIdentifier FutureStrictReserved() {
525 return PreParserIdentifier(kFutureStrictReservedIdentifier);
527 static PreParserIdentifier Yield() {
528 return PreParserIdentifier(kYieldIdentifier);
530 bool IsEval() { return type_ == kEvalIdentifier; }
531 bool IsArguments() { return type_ == kArgumentsIdentifier; }
532 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
533 bool IsYield() { return type_ == kYieldIdentifier; }
534 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
535 bool IsFutureStrictReserved() {
536 return type_ == kFutureStrictReservedIdentifier;
538 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
543 kFutureReservedIdentifier,
544 kFutureStrictReservedIdentifier,
549 explicit PreParserIdentifier(Type type) : type_(type) {}
552 friend class PreParserExpression;
556 // Bits 0 and 1 are used to identify the type of expression:
557 // If bit 0 is set, it's an identifier.
558 // if bit 1 is set, it's a string literal.
559 // If neither is set, it's no particular type, and both set isn't
561 class PreParserExpression {
563 static PreParserExpression Default() {
564 return PreParserExpression(kUnknownExpression);
567 static PreParserExpression FromIdentifier(PreParserIdentifier id) {
568 return PreParserExpression(kIdentifierFlag |
569 (id.type_ << kIdentifierShift));
572 static PreParserExpression StringLiteral() {
573 return PreParserExpression(kUnknownStringLiteral);
576 static PreParserExpression UseStrictStringLiteral() {
577 return PreParserExpression(kUseStrictString);
580 static PreParserExpression This() {
581 return PreParserExpression(kThisExpression);
584 static PreParserExpression ThisProperty() {
585 return PreParserExpression(kThisPropertyExpression);
588 static PreParserExpression Property() {
589 return PreParserExpression(kPropertyExpression);
592 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
594 // Only works corretly if it is actually an identifier expression.
595 PreParserIdentifier AsIdentifier() {
596 return PreParserIdentifier(
597 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
600 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
602 bool IsUseStrictLiteral() {
603 return (code_ & kStringLiteralMask) == kUseStrictString;
606 bool IsThis() { return code_ == kThisExpression; }
608 bool IsThisProperty() { return code_ == kThisPropertyExpression; }
611 return code_ == kPropertyExpression || code_ == kThisPropertyExpression;
614 bool IsValidLeftHandSide() {
615 return IsIdentifier() || IsProperty();
618 // At the moment PreParser doesn't track these expression types.
619 bool IsFunctionLiteral() const { return false; }
620 bool IsCall() const { return false; }
621 bool IsCallNew() const { return false; }
623 PreParserExpression AsFunctionLiteral() { return *this; }
625 // Dummy implementation for making expression->somefunc() work in both Parser
627 PreParserExpression* operator->() { return this; }
629 // More dummy implementations of things PreParser doesn't need to track:
630 void set_index(int index) {} // For YieldExpressions
631 void set_parenthesized() {}
634 // Least significant 2 bits are used as flags. Bits 0 and 1 represent
635 // identifiers or strings literals, and are mutually exclusive, but can both
636 // be absent. If the expression is an identifier or a string literal, the
637 // other bits describe the type (see PreParserIdentifier::Type and string
638 // literal constants below).
640 kUnknownExpression = 0,
642 kIdentifierFlag = 1, // Used to detect labels.
643 kIdentifierShift = 3,
645 kStringLiteralFlag = 2, // Used to detect directive prologue.
646 kUnknownStringLiteral = kStringLiteralFlag,
647 kUseStrictString = kStringLiteralFlag | 8,
648 kStringLiteralMask = kUseStrictString,
650 // Below here applies if neither identifier nor string literal. Reserve the
651 // 2 least significant bits for flags.
652 kThisExpression = 1 << 2,
653 kThisPropertyExpression = 2 << 2,
654 kPropertyExpression = 3 << 2
657 explicit PreParserExpression(int expression_code) : code_(expression_code) {}
663 // PreParserExpressionList doesn't actually store the expressions because
664 // PreParser doesn't need to.
665 class PreParserExpressionList {
667 // These functions make list->Add(some_expression) work (and do nothing).
668 PreParserExpressionList() : length_(0) {}
669 PreParserExpressionList* operator->() { return this; }
670 void Add(PreParserExpression, void*) { ++length_; }
671 int length() const { return length_; }
677 class PreParserScope {
679 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type)
680 : scope_type_(scope_type) {
681 strict_mode_ = outer_scope ? outer_scope->strict_mode() : SLOPPY;
684 ScopeType type() { return scope_type_; }
685 StrictMode strict_mode() const { return strict_mode_; }
686 void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
689 ScopeType scope_type_;
690 StrictMode strict_mode_;
694 class PreParserFactory {
696 explicit PreParserFactory(void* extra_param) {}
697 PreParserExpression NewLiteral(PreParserIdentifier identifier,
699 return PreParserExpression::Default();
701 PreParserExpression NewNumberLiteral(double number,
703 return PreParserExpression::Default();
705 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
706 PreParserIdentifier js_flags,
709 return PreParserExpression::Default();
711 PreParserExpression NewArrayLiteral(PreParserExpressionList values,
714 return PreParserExpression::Default();
716 PreParserExpression NewObjectLiteralProperty(bool is_getter,
717 PreParserExpression value,
719 return PreParserExpression::Default();
721 PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
722 PreParserExpression value) {
723 return PreParserExpression::Default();
725 PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
727 int boilerplate_properties,
730 return PreParserExpression::Default();
732 PreParserExpression NewVariableProxy(void* generator_variable) {
733 return PreParserExpression::Default();
735 PreParserExpression NewProperty(PreParserExpression obj,
736 PreParserExpression key,
739 return PreParserExpression::ThisProperty();
741 return PreParserExpression::Property();
743 PreParserExpression NewUnaryOperation(Token::Value op,
744 PreParserExpression expression,
746 return PreParserExpression::Default();
748 PreParserExpression NewBinaryOperation(Token::Value op,
749 PreParserExpression left,
750 PreParserExpression right, int pos) {
751 return PreParserExpression::Default();
753 PreParserExpression NewCompareOperation(Token::Value op,
754 PreParserExpression left,
755 PreParserExpression right, int pos) {
756 return PreParserExpression::Default();
758 PreParserExpression NewAssignment(Token::Value op,
759 PreParserExpression left,
760 PreParserExpression right,
762 return PreParserExpression::Default();
764 PreParserExpression NewYield(PreParserExpression generator_object,
765 PreParserExpression expression,
766 Yield::Kind yield_kind,
768 return PreParserExpression::Default();
770 PreParserExpression NewConditional(PreParserExpression condition,
771 PreParserExpression then_expression,
772 PreParserExpression else_expression,
774 return PreParserExpression::Default();
776 PreParserExpression NewCountOperation(Token::Value op,
778 PreParserExpression expression,
780 return PreParserExpression::Default();
782 PreParserExpression NewCall(PreParserExpression expression,
783 PreParserExpressionList arguments,
785 return PreParserExpression::Default();
787 PreParserExpression NewCallNew(PreParserExpression expression,
788 PreParserExpressionList arguments,
790 return PreParserExpression::Default();
797 class PreParserTraits {
800 // TODO(marja): To be removed. The Traits object should contain all the data
802 typedef PreParser* Parser;
804 // Used by FunctionState and BlockState.
805 typedef PreParserScope Scope;
806 // PreParser doesn't need to store generator variables.
807 typedef void GeneratorVariable;
808 // No interaction with Zones.
811 // Return types for traversing functions.
812 typedef PreParserIdentifier Identifier;
813 typedef PreParserExpression Expression;
814 typedef PreParserExpression YieldExpression;
815 typedef PreParserExpression FunctionLiteral;
816 typedef PreParserExpression ObjectLiteralProperty;
817 typedef PreParserExpression Literal;
818 typedef PreParserExpressionList ExpressionList;
819 typedef PreParserExpressionList PropertyList;
821 // For constructing objects returned by the traversing functions.
822 typedef PreParserFactory Factory;
825 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
827 // Custom operations executed when FunctionStates are created and
828 // destructed. (The PreParser doesn't need to do anything.)
829 template<typename FunctionState>
830 static void SetUpFunctionState(FunctionState* function_state, void*) {}
831 template<typename FunctionState>
832 static void TearDownFunctionState(FunctionState* function_state) {}
834 // Helper functions for recursive descent.
835 static bool IsEvalOrArguments(PreParserIdentifier identifier) {
836 return identifier.IsEvalOrArguments();
839 // Returns true if the expression is of type "this.foo".
840 static bool IsThisProperty(PreParserExpression expression) {
841 return expression.IsThisProperty();
844 static bool IsIdentifier(PreParserExpression expression) {
845 return expression.IsIdentifier();
848 static bool IsBoilerplateProperty(PreParserExpression property) {
849 // PreParser doesn't count boilerplate properties.
853 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
857 // Functions for encapsulating the differences between parsing and preparsing;
858 // operations interleaved with the recursive descent.
859 static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
860 // PreParser should not use FuncNameInferrer.
863 static void PushPropertyName(FuncNameInferrer* fni,
864 PreParserExpression expression) {
865 // PreParser should not use FuncNameInferrer.
869 static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
870 PreParserScope* scope, PreParserExpression value, bool* has_function) {}
872 static void CheckAssigningFunctionLiteralToProperty(
873 PreParserExpression left, PreParserExpression right) {}
875 // PreParser doesn't need to keep track of eval calls.
876 static void CheckPossibleEvalCall(PreParserExpression expression,
877 PreParserScope* scope) {}
879 static PreParserExpression MarkExpressionAsLValue(
880 PreParserExpression expression) {
881 // TODO(marja): To be able to produce the same errors, the preparser needs
882 // to start tracking which expressions are variables and which are lvalues.
886 // Checks LHS expression for assignment and prefix/postfix increment/decrement
888 void CheckStrictModeLValue(PreParserExpression expression, bool* ok);
890 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
891 PreParserExpression y,
894 PreParserFactory* factory) {
898 PreParserExpression BuildUnaryExpression(PreParserExpression expression,
899 Token::Value op, int pos,
900 PreParserFactory* factory) {
901 return PreParserExpression::Default();
905 void ReportMessageAt(Scanner::Location location,
907 Vector<const char*> args,
908 bool is_reference_error = false);
909 void ReportMessageAt(Scanner::Location location,
911 const char* name_opt,
912 bool is_reference_error = false);
913 void ReportMessageAt(int start_pos,
916 const char* name_opt,
917 bool is_reference_error = false);
919 // "null" return type creators.
920 static PreParserIdentifier EmptyIdentifier() {
921 return PreParserIdentifier::Default();
923 static PreParserExpression EmptyExpression() {
924 return PreParserExpression::Default();
926 static PreParserExpression EmptyLiteral() {
927 return PreParserExpression::Default();
929 static PreParserExpressionList NullExpressionList() {
930 return PreParserExpressionList();
933 // Odd-ball literal creators.
934 static PreParserExpression GetLiteralTheHole(int position,
935 PreParserFactory* factory) {
936 return PreParserExpression::Default();
939 // Producing data during the recursive descent.
940 PreParserIdentifier GetSymbol(Scanner* scanner);
941 static PreParserIdentifier NextLiteralString(Scanner* scanner,
942 PretenureFlag tenured) {
943 return PreParserIdentifier::Default();
946 static PreParserExpression ThisExpression(PreParserScope* scope,
947 PreParserFactory* factory) {
948 return PreParserExpression::This();
951 static PreParserExpression ExpressionFromLiteral(
952 Token::Value token, int pos, Scanner* scanner,
953 PreParserFactory* factory) {
954 return PreParserExpression::Default();
957 static PreParserExpression ExpressionFromIdentifier(
958 PreParserIdentifier name, int pos, PreParserScope* scope,
959 PreParserFactory* factory) {
960 return PreParserExpression::FromIdentifier(name);
963 PreParserExpression ExpressionFromString(int pos,
965 PreParserFactory* factory = NULL);
967 static PreParserExpressionList NewExpressionList(int size, void* zone) {
968 return PreParserExpressionList();
971 static PreParserExpressionList NewPropertyList(int size, void* zone) {
972 return PreParserExpressionList();
975 // Temporary glue; these functions will move to ParserBase.
976 PreParserExpression ParseV8Intrinsic(bool* ok);
977 PreParserExpression ParseFunctionLiteral(
978 PreParserIdentifier name,
979 Scanner::Location function_name_location,
980 bool name_is_strict_reserved,
982 int function_token_position,
983 FunctionLiteral::FunctionType type,
987 PreParser* pre_parser_;
991 // Preparsing checks a JavaScript program and emits preparse-data that helps
992 // a later parsing to be faster.
993 // See preparse-data-format.h for the data format.
995 // The PreParser checks that the syntax follows the grammar for JavaScript,
996 // and collects some information about the program along the way.
997 // The grammar check is only performed in order to understand the program
998 // sufficiently to deduce some information about it, that can be used
999 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
1000 // rather it is to speed up properly written and correct programs.
1001 // That means that contextual checks (like a label being declared where
1002 // it is used) are generally omitted.
1003 class PreParser : public ParserBase<PreParserTraits> {
1005 typedef PreParserIdentifier Identifier;
1006 typedef PreParserExpression Expression;
1008 enum PreParseResult {
1009 kPreParseStackOverflow,
1013 PreParser(Scanner* scanner, ParserRecorder* log, uintptr_t stack_limit)
1014 : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, NULL,
1017 // Pre-parse the program from the character stream; returns true on
1018 // success (even if parsing failed, the pre-parse data successfully
1019 // captured the syntax error), and false if a stack-overflow happened
1021 PreParseResult PreParseProgram() {
1022 PreParserScope scope(scope_, GLOBAL_SCOPE);
1023 FunctionState top_scope(&function_state_, &scope_, &scope, NULL);
1025 int start_position = scanner()->peek_location().beg_pos;
1026 ParseSourceElements(Token::EOS, &ok);
1027 if (stack_overflow()) return kPreParseStackOverflow;
1029 ReportUnexpectedToken(scanner()->current_token());
1030 } else if (scope_->strict_mode() == STRICT) {
1031 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
1033 return kPreParseSuccess;
1036 // Parses a single function literal, from the opening parentheses before
1037 // parameters to the closing brace after the body.
1038 // Returns a FunctionEntry describing the body of the function in enough
1039 // detail that it can be lazily compiled.
1040 // The scanner is expected to have matched the "function" or "function*"
1041 // keyword and parameters, and have consumed the initial '{'.
1042 // At return, unless an error occurred, the scanner is positioned before the
1044 PreParseResult PreParseLazyFunction(StrictMode strict_mode,
1046 ParserRecorder* log);
1049 friend class PreParserTraits;
1051 // These types form an algebra over syntactic categories that is just
1052 // rich enough to let us recognize and propagate the constructs that
1053 // are either being counted in the preparser data, or is important
1054 // to throw the correct syntax error exceptions.
1056 enum VariableDeclarationContext {
1062 // If a list of variable declarations includes any initializers.
1063 enum VariableDeclarationProperties {
1070 static Statement Default() {
1071 return Statement(kUnknownStatement);
1074 static Statement FunctionDeclaration() {
1075 return Statement(kFunctionDeclaration);
1078 // Creates expression statement from expression.
1079 // Preserves being an unparenthesized string literal, possibly
1081 static Statement ExpressionStatement(Expression expression) {
1082 if (expression.IsUseStrictLiteral()) {
1083 return Statement(kUseStrictExpressionStatement);
1085 if (expression.IsStringLiteral()) {
1086 return Statement(kStringLiteralExpressionStatement);
1091 bool IsStringLiteral() {
1092 return code_ == kStringLiteralExpressionStatement;
1095 bool IsUseStrictLiteral() {
1096 return code_ == kUseStrictExpressionStatement;
1099 bool IsFunctionDeclaration() {
1100 return code_ == kFunctionDeclaration;
1106 kStringLiteralExpressionStatement,
1107 kUseStrictExpressionStatement,
1108 kFunctionDeclaration
1111 explicit Statement(Type code) : code_(code) {}
1115 enum SourceElements {
1116 kUnknownSourceElements
1119 // All ParseXXX functions take as the last argument an *ok parameter
1120 // which is set to false if parsing failed; it is unchanged otherwise.
1121 // By making the 'exception handling' explicit, we are forced to check
1122 // for failure at the call sites.
1123 Statement ParseSourceElement(bool* ok);
1124 SourceElements ParseSourceElements(int end_token, bool* ok);
1125 Statement ParseStatement(bool* ok);
1126 Statement ParseFunctionDeclaration(bool* ok);
1127 Statement ParseBlock(bool* ok);
1128 Statement ParseVariableStatement(VariableDeclarationContext var_context,
1130 Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
1131 VariableDeclarationProperties* decl_props,
1134 Statement ParseExpressionOrLabelledStatement(bool* ok);
1135 Statement ParseIfStatement(bool* ok);
1136 Statement ParseContinueStatement(bool* ok);
1137 Statement ParseBreakStatement(bool* ok);
1138 Statement ParseReturnStatement(bool* ok);
1139 Statement ParseWithStatement(bool* ok);
1140 Statement ParseSwitchStatement(bool* ok);
1141 Statement ParseDoWhileStatement(bool* ok);
1142 Statement ParseWhileStatement(bool* ok);
1143 Statement ParseForStatement(bool* ok);
1144 Statement ParseThrowStatement(bool* ok);
1145 Statement ParseTryStatement(bool* ok);
1146 Statement ParseDebuggerStatement(bool* ok);
1147 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
1148 Expression ParseObjectLiteral(bool* ok);
1149 Expression ParseV8Intrinsic(bool* ok);
1151 Expression ParseFunctionLiteral(
1153 Scanner::Location function_name_location,
1154 bool name_is_strict_reserved,
1156 int function_token_pos,
1157 FunctionLiteral::FunctionType function_type,
1159 void ParseLazyFunctionLiteralBody(bool* ok);
1161 // Logs the currently parsed literal as a symbol in the preparser data.
1163 // Log the currently parsed string literal.
1164 Expression GetStringSymbol();
1166 bool CheckInOrOf(bool accept_OF);
1169 template<class Traits>
1170 ParserBase<Traits>::FunctionState::FunctionState(
1171 FunctionState** function_state_stack,
1172 typename Traits::Type::Scope** scope_stack,
1173 typename Traits::Type::Scope* scope,
1174 typename Traits::Type::Zone* extra_param)
1175 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
1176 next_handler_index_(0),
1177 expected_property_count_(0),
1178 is_generator_(false),
1179 generator_object_variable_(NULL),
1180 function_state_stack_(function_state_stack),
1181 outer_function_state_(*function_state_stack),
1182 scope_stack_(scope_stack),
1183 outer_scope_(*scope_stack),
1185 saved_ast_node_id_(0),
1186 factory_(extra_param) {
1187 *scope_stack_ = scope;
1188 *function_state_stack = this;
1189 Traits::SetUpFunctionState(this, extra_param);
1193 template<class Traits>
1194 ParserBase<Traits>::FunctionState::~FunctionState() {
1195 *scope_stack_ = outer_scope_;
1196 *function_state_stack_ = outer_function_state_;
1197 Traits::TearDownFunctionState(this);
1201 template<class Traits>
1202 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
1203 Scanner::Location source_location = scanner()->location();
1205 // Four of the tokens are treated specially
1208 return ReportMessageAt(source_location, "unexpected_eos");
1210 return ReportMessageAt(source_location, "unexpected_token_number");
1212 return ReportMessageAt(source_location, "unexpected_token_string");
1213 case Token::IDENTIFIER:
1214 return ReportMessageAt(source_location, "unexpected_token_identifier");
1215 case Token::FUTURE_RESERVED_WORD:
1216 return ReportMessageAt(source_location, "unexpected_reserved");
1218 case Token::FUTURE_STRICT_RESERVED_WORD:
1219 return ReportMessageAt(source_location, strict_mode() == SLOPPY
1220 ? "unexpected_token_identifier" : "unexpected_strict_reserved");
1222 const char* name = Token::String(token);
1223 ASSERT(name != NULL);
1224 Traits::ReportMessageAt(
1225 source_location, "unexpected_token", Vector<const char*>(&name, 1));
1230 template<class Traits>
1231 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
1232 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
1234 Token::Value next = Next();
1235 if (next == Token::IDENTIFIER) {
1236 IdentifierT name = this->GetSymbol(scanner());
1237 if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
1238 strict_mode() == STRICT && this->IsEvalOrArguments(name)) {
1239 ReportMessageAt(scanner()->location(), "strict_eval_arguments");
1243 } else if (strict_mode() == SLOPPY &&
1244 (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1245 (next == Token::YIELD && !is_generator()))) {
1246 return this->GetSymbol(scanner());
1248 this->ReportUnexpectedToken(next);
1250 return Traits::EmptyIdentifier();
1255 template <class Traits>
1256 typename ParserBase<Traits>::IdentifierT ParserBase<
1257 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
1259 Token::Value next = Next();
1260 if (next == Token::IDENTIFIER) {
1261 *is_strict_reserved = false;
1262 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1263 (next == Token::YIELD && !this->is_generator())) {
1264 *is_strict_reserved = true;
1266 ReportUnexpectedToken(next);
1268 return Traits::EmptyIdentifier();
1270 return this->GetSymbol(scanner());
1274 template <class Traits>
1275 typename ParserBase<Traits>::IdentifierT
1276 ParserBase<Traits>::ParseIdentifierName(bool* ok) {
1277 Token::Value next = Next();
1278 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
1279 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
1280 this->ReportUnexpectedToken(next);
1282 return Traits::EmptyIdentifier();
1284 return this->GetSymbol(scanner());
1288 template <class Traits>
1289 typename ParserBase<Traits>::IdentifierT
1290 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
1293 IdentifierT result = ParseIdentifierName(ok);
1294 if (!*ok) return Traits::EmptyIdentifier();
1295 scanner()->IsGetOrSet(is_get, is_set);
1300 template <class Traits>
1301 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
1302 bool seen_equal, bool* ok) {
1303 int pos = peek_position();
1304 if (!scanner()->ScanRegExpPattern(seen_equal)) {
1306 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
1308 return Traits::EmptyExpression();
1311 int literal_index = function_state_->NextMaterializedLiteralIndex();
1313 IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED);
1314 if (!scanner()->ScanRegExpFlags()) {
1316 ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
1318 return Traits::EmptyExpression();
1320 IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED);
1322 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
1326 #define CHECK_OK ok); \
1327 if (!*ok) return this->EmptyExpression(); \
1329 #define DUMMY ) // to make indentation work
1332 // Used in functions where the return type is not ExpressionT.
1333 #define CHECK_OK_CUSTOM(x) ok); \
1334 if (!*ok) return this->x(); \
1336 #define DUMMY ) // to make indentation work
1339 template <class Traits>
1340 typename ParserBase<Traits>::ExpressionT
1341 ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
1342 // PrimaryExpression ::
1353 // '(' Expression ')'
1355 int pos = peek_position();
1356 ExpressionT result = this->EmptyExpression();
1357 Token::Value token = peek();
1360 Consume(Token::THIS);
1361 result = this->ThisExpression(scope_, factory());
1365 case Token::NULL_LITERAL:
1366 case Token::TRUE_LITERAL:
1367 case Token::FALSE_LITERAL:
1370 result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
1373 case Token::IDENTIFIER:
1375 case Token::FUTURE_STRICT_RESERVED_WORD: {
1376 // Using eval or arguments in this context is OK even in strict mode.
1377 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1378 result = this->ExpressionFromIdentifier(name, pos, scope_, factory());
1382 case Token::STRING: {
1383 Consume(Token::STRING);
1384 result = this->ExpressionFromString(pos, scanner(), factory());
1388 case Token::ASSIGN_DIV:
1389 result = this->ParseRegExpLiteral(true, CHECK_OK);
1393 result = this->ParseRegExpLiteral(false, CHECK_OK);
1397 result = this->ParseArrayLiteral(CHECK_OK);
1401 result = this->ParseObjectLiteral(CHECK_OK);
1405 Consume(Token::LPAREN);
1406 // Heuristically try to detect immediately called functions before
1407 // seeing the call parentheses.
1408 parenthesized_function_ = (peek() == Token::FUNCTION);
1409 result = this->ParseExpression(true, CHECK_OK);
1410 Expect(Token::RPAREN, CHECK_OK);
1414 if (allow_natives_syntax() || extension_ != NULL) {
1415 result = this->ParseV8Intrinsic(CHECK_OK);
1418 // If we're not allowing special syntax we fall-through to the
1423 ReportUnexpectedToken(token);
1432 template <class Traits>
1433 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
1434 bool accept_IN, bool* ok) {
1436 // AssignmentExpression
1437 // Expression ',' AssignmentExpression
1439 ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1440 while (peek() == Token::COMMA) {
1441 Expect(Token::COMMA, CHECK_OK);
1442 int pos = position();
1443 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1444 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
1450 template <class Traits>
1451 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
1454 // '[' Expression? (',' Expression?)* ']'
1456 int pos = peek_position();
1457 typename Traits::Type::ExpressionList values =
1458 this->NewExpressionList(4, zone_);
1459 Expect(Token::LBRACK, CHECK_OK);
1460 while (peek() != Token::RBRACK) {
1461 ExpressionT elem = this->EmptyExpression();
1462 if (peek() == Token::COMMA) {
1463 elem = this->GetLiteralTheHole(peek_position(), factory());
1465 elem = this->ParseAssignmentExpression(true, CHECK_OK);
1467 values->Add(elem, zone_);
1468 if (peek() != Token::RBRACK) {
1469 Expect(Token::COMMA, CHECK_OK);
1472 Expect(Token::RBRACK, CHECK_OK);
1474 // Update the scope information before the pre-parsing bailout.
1475 int literal_index = function_state_->NextMaterializedLiteralIndex();
1477 return factory()->NewArrayLiteral(values, literal_index, pos);
1481 template <class Traits>
1482 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
1486 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
1487 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1489 // (Except that trailing comma is not required and not allowed.)
1491 int pos = peek_position();
1492 typename Traits::Type::PropertyList properties =
1493 this->NewPropertyList(4, zone_);
1494 int number_of_boilerplate_properties = 0;
1495 bool has_function = false;
1497 ObjectLiteralChecker checker(this, strict_mode());
1499 Expect(Token::LBRACE, CHECK_OK);
1501 while (peek() != Token::RBRACE) {
1502 if (fni_ != NULL) fni_->Enter();
1504 typename Traits::Type::Literal key = this->EmptyLiteral();
1505 Token::Value next = peek();
1506 int next_pos = peek_position();
1509 case Token::FUTURE_RESERVED_WORD:
1510 case Token::FUTURE_STRICT_RESERVED_WORD:
1511 case Token::IDENTIFIER: {
1512 bool is_getter = false;
1513 bool is_setter = false;
1515 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1516 if (fni_ != NULL) this->PushLiteralName(fni_, id);
1518 if ((is_getter || is_setter) && peek() != Token::COLON) {
1519 // Special handling of getter and setter syntax:
1520 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
1521 // We have already read the "get" or "set" keyword.
1522 Token::Value next = Next();
1523 if (next != i::Token::IDENTIFIER &&
1524 next != i::Token::FUTURE_RESERVED_WORD &&
1525 next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1526 next != i::Token::NUMBER &&
1527 next != i::Token::STRING &&
1528 !Token::IsKeyword(next)) {
1529 ReportUnexpectedToken(next);
1531 return this->EmptyLiteral();
1533 // Validate the property.
1534 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
1535 checker.CheckProperty(next, type, CHECK_OK);
1536 IdentifierT name = this->GetSymbol(scanner_);
1537 typename Traits::Type::FunctionLiteral value =
1538 this->ParseFunctionLiteral(
1539 name, scanner()->location(),
1540 false, // reserved words are allowed here
1541 false, // not a generator
1542 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
1544 // Allow any number of parameters for compatibilty with JSC.
1545 // Specification only allows zero parameters for get and one for set.
1546 typename Traits::Type::ObjectLiteralProperty property =
1547 factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
1548 if (this->IsBoilerplateProperty(property)) {
1549 number_of_boilerplate_properties++;
1551 properties->Add(property, zone());
1552 if (peek() != Token::RBRACE) {
1553 // Need {} because of the CHECK_OK macro.
1554 Expect(Token::COMMA, CHECK_OK);
1561 continue; // restart the while
1563 // Failed to parse as get/set property, so it's just a normal property
1564 // (which might be called "get" or "set" or something else).
1565 key = factory()->NewLiteral(id, next_pos);
1568 case Token::STRING: {
1569 Consume(Token::STRING);
1570 IdentifierT string = this->GetSymbol(scanner_);
1571 if (fni_ != NULL) this->PushLiteralName(fni_, string);
1573 if (this->IsArrayIndex(string, &index)) {
1574 key = factory()->NewNumberLiteral(index, next_pos);
1577 key = factory()->NewLiteral(string, next_pos);
1580 case Token::NUMBER: {
1581 Consume(Token::NUMBER);
1582 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
1587 if (Token::IsKeyword(next)) {
1589 IdentifierT string = this->GetSymbol(scanner_);
1590 key = factory()->NewLiteral(string, next_pos);
1592 Token::Value next = Next();
1593 ReportUnexpectedToken(next);
1595 return this->EmptyLiteral();
1599 // Validate the property
1600 checker.CheckProperty(next, kValueProperty, CHECK_OK);
1602 Expect(Token::COLON, CHECK_OK);
1603 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK);
1605 typename Traits::Type::ObjectLiteralProperty property =
1606 factory()->NewObjectLiteralProperty(key, value);
1608 // Mark top-level object literals that contain function literals and
1609 // pretenure the literal so it can be added as a constant function
1610 // property. (Parser only.)
1611 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value,
1614 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
1615 if (this->IsBoilerplateProperty(property)) {
1616 number_of_boilerplate_properties++;
1618 properties->Add(property, zone());
1620 // TODO(1240767): Consider allowing trailing comma.
1621 if (peek() != Token::RBRACE) {
1622 // Need {} because of the CHECK_OK macro.
1623 Expect(Token::COMMA, CHECK_OK);
1631 Expect(Token::RBRACE, CHECK_OK);
1633 // Computation of literal_index must happen before pre parse bailout.
1634 int literal_index = function_state_->NextMaterializedLiteralIndex();
1636 return factory()->NewObjectLiteral(properties,
1638 number_of_boilerplate_properties,
1644 template <class Traits>
1645 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
1648 // '(' (AssignmentExpression)*[','] ')'
1650 typename Traits::Type::ExpressionList result =
1651 this->NewExpressionList(4, zone_);
1652 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
1653 bool done = (peek() == Token::RPAREN);
1655 ExpressionT argument = this->ParseAssignmentExpression(
1656 true, CHECK_OK_CUSTOM(NullExpressionList));
1657 result->Add(argument, zone_);
1658 if (result->length() > Code::kMaxArguments) {
1659 ReportMessageAt(scanner()->location(), "too_many_arguments");
1661 return this->NullExpressionList();
1663 done = (peek() == Token::RPAREN);
1665 // Need {} because of the CHECK_OK_CUSTOM macro.
1666 Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList));
1669 Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
1674 template <class Traits>
1675 typename ParserBase<Traits>::ExpressionT
1676 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
1677 // AssignmentExpression ::
1678 // ConditionalExpression
1680 // LeftHandSideExpression AssignmentOperator AssignmentExpression
1682 Scanner::Location lhs_location = scanner()->peek_location();
1684 if (peek() == Token::YIELD && is_generator()) {
1685 return this->ParseYieldExpression(ok);
1688 if (fni_ != NULL) fni_->Enter();
1689 ExpressionT expression =
1690 this->ParseConditionalExpression(accept_IN, CHECK_OK);
1692 if (!Token::IsAssignmentOp(peek())) {
1693 if (fni_ != NULL) fni_->Leave();
1694 // Parsed conditional expression only (no assignment).
1698 if (!expression->IsValidLeftHandSide()) {
1699 this->ReportMessageAt(lhs_location, "invalid_lhs_in_assignment", true);
1701 return this->EmptyExpression();
1704 if (strict_mode() == STRICT) {
1705 // Assignment to eval or arguments is disallowed in strict mode.
1706 this->CheckStrictModeLValue(expression, CHECK_OK);
1708 expression = this->MarkExpressionAsLValue(expression);
1710 Token::Value op = Next(); // Get assignment operator.
1711 int pos = position();
1712 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1714 // TODO(1231235): We try to estimate the set of properties set by
1715 // constructors. We define a new property whenever there is an
1716 // assignment to a property of 'this'. We should probably only add
1717 // properties if we haven't seen them before. Otherwise we'll
1718 // probably overestimate the number of properties.
1719 if (op == Token::ASSIGN && this->IsThisProperty(expression)) {
1720 function_state_->AddProperty();
1723 this->CheckAssigningFunctionLiteralToProperty(expression, right);
1726 // Check if the right hand side is a call to avoid inferring a
1727 // name if we're dealing with "a = function(){...}();"-like
1729 if ((op == Token::INIT_VAR
1730 || op == Token::INIT_CONST_LEGACY
1731 || op == Token::ASSIGN)
1732 && (!right->IsCall() && !right->IsCallNew())) {
1735 fni_->RemoveLastFunction();
1740 return factory()->NewAssignment(op, expression, right, pos);
1743 template <class Traits>
1744 typename ParserBase<Traits>::ExpressionT
1745 ParserBase<Traits>::ParseYieldExpression(bool* ok) {
1746 // YieldExpression ::
1747 // 'yield' '*'? AssignmentExpression
1748 int pos = peek_position();
1749 Expect(Token::YIELD, CHECK_OK);
1751 Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
1752 ExpressionT generator_object =
1753 factory()->NewVariableProxy(function_state_->generator_object_variable());
1754 ExpressionT expression =
1755 ParseAssignmentExpression(false, CHECK_OK);
1756 typename Traits::Type::YieldExpression yield =
1757 factory()->NewYield(generator_object, expression, kind, pos);
1758 if (kind == Yield::DELEGATING) {
1759 yield->set_index(function_state_->NextHandlerIndex());
1766 template <class Traits>
1767 typename ParserBase<Traits>::ExpressionT
1768 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
1769 // ConditionalExpression ::
1770 // LogicalOrExpression
1771 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
1773 int pos = peek_position();
1774 // We start using the binary expression parser for prec >= 4 only!
1775 ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK);
1776 if (peek() != Token::CONDITIONAL) return expression;
1777 Consume(Token::CONDITIONAL);
1778 // In parsing the first assignment expression in conditional
1779 // expressions we always accept the 'in' keyword; see ECMA-262,
1780 // section 11.12, page 58.
1781 ExpressionT left = ParseAssignmentExpression(true, CHECK_OK);
1782 Expect(Token::COLON, CHECK_OK);
1783 ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK);
1784 return factory()->NewConditional(expression, left, right, pos);
1789 template <class Traits>
1790 typename ParserBase<Traits>::ExpressionT
1791 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
1793 ExpressionT x = this->ParseUnaryExpression(CHECK_OK);
1794 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
1796 while (Precedence(peek(), accept_IN) == prec1) {
1797 Token::Value op = Next();
1798 int pos = position();
1799 ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
1801 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
1806 // For now we distinguish between comparisons and other binary
1807 // operations. (We could combine the two and get rid of this
1808 // code and AST node eventually.)
1809 if (Token::IsCompareOp(op)) {
1810 // We have a comparison.
1811 Token::Value cmp = op;
1813 case Token::NE: cmp = Token::EQ; break;
1814 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
1817 x = factory()->NewCompareOperation(cmp, x, y, pos);
1819 // The comparison was negated - add a NOT.
1820 x = factory()->NewUnaryOperation(Token::NOT, x, pos);
1824 // We have a "normal" binary operation.
1825 x = factory()->NewBinaryOperation(op, x, y, pos);
1833 template <class Traits>
1834 typename ParserBase<Traits>::ExpressionT
1835 ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
1836 // UnaryExpression ::
1837 // PostfixExpression
1838 // 'delete' UnaryExpression
1839 // 'void' UnaryExpression
1840 // 'typeof' UnaryExpression
1841 // '++' UnaryExpression
1842 // '--' UnaryExpression
1843 // '+' UnaryExpression
1844 // '-' UnaryExpression
1845 // '~' UnaryExpression
1846 // '!' UnaryExpression
1848 Token::Value op = peek();
1849 if (Token::IsUnaryOp(op)) {
1851 int pos = position();
1852 ExpressionT expression = ParseUnaryExpression(CHECK_OK);
1854 // "delete identifier" is a syntax error in strict mode.
1855 if (op == Token::DELETE && strict_mode() == STRICT &&
1856 this->IsIdentifier(expression)) {
1857 ReportMessage("strict_delete", Vector<const char*>::empty());
1859 return this->EmptyExpression();
1862 // Allow Traits do rewrite the expression.
1863 return this->BuildUnaryExpression(expression, op, pos, factory());
1864 } else if (Token::IsCountOp(op)) {
1866 Scanner::Location lhs_location = scanner()->peek_location();
1867 ExpressionT expression = ParseUnaryExpression(CHECK_OK);
1868 if (!expression->IsValidLeftHandSide()) {
1869 ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true);
1871 return this->EmptyExpression();
1874 if (strict_mode() == STRICT) {
1875 // Prefix expression operand in strict mode may not be eval or arguments.
1876 this->CheckStrictModeLValue(expression, CHECK_OK);
1878 this->MarkExpressionAsLValue(expression);
1880 return factory()->NewCountOperation(op,
1886 return this->ParsePostfixExpression(ok);
1891 template <class Traits>
1892 typename ParserBase<Traits>::ExpressionT
1893 ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
1894 // PostfixExpression ::
1895 // LeftHandSideExpression ('++' | '--')?
1897 Scanner::Location lhs_location = scanner()->peek_location();
1898 ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK);
1899 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
1900 Token::IsCountOp(peek())) {
1901 if (!expression->IsValidLeftHandSide()) {
1902 ReportMessageAt(lhs_location, "invalid_lhs_in_postfix_op", true);
1904 return this->EmptyExpression();
1907 if (strict_mode() == STRICT) {
1908 // Postfix expression operand in strict mode may not be eval or arguments.
1909 this->CheckStrictModeLValue(expression, CHECK_OK);
1911 expression = this->MarkExpressionAsLValue(expression);
1913 Token::Value next = Next();
1915 factory()->NewCountOperation(next,
1916 false /* postfix */,
1924 template <class Traits>
1925 typename ParserBase<Traits>::ExpressionT
1926 ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
1927 // LeftHandSideExpression ::
1928 // (NewExpression | MemberExpression) ...
1930 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
1934 case Token::LBRACK: {
1935 Consume(Token::LBRACK);
1936 int pos = position();
1937 ExpressionT index = ParseExpression(true, CHECK_OK);
1938 result = factory()->NewProperty(result, index, pos);
1939 Expect(Token::RBRACK, CHECK_OK);
1943 case Token::LPAREN: {
1945 if (scanner()->current_token() == Token::IDENTIFIER) {
1946 // For call of an identifier we want to report position of
1947 // the identifier as position of the call in the stack trace.
1950 // For other kinds of calls we record position of the parenthesis as
1951 // position of the call. Note that this is extremely important for
1952 // expressions of the form function(){...}() for which call position
1953 // should not point to the closing brace otherwise it will intersect
1954 // with positions recorded for function literal and confuse debugger.
1955 pos = peek_position();
1956 // Also the trailing parenthesis are a hint that the function will
1957 // be called immediately. If we happen to have parsed a preceding
1958 // function literal eagerly, we can also compile it eagerly.
1959 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
1960 result->AsFunctionLiteral()->set_parenthesized();
1963 typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK);
1965 // Keep track of eval() calls since they disable all local variable
1967 // The calls that need special treatment are the
1968 // direct eval calls. These calls are all of the form eval(...), with
1969 // no explicit receiver.
1970 // These calls are marked as potentially direct eval calls. Whether
1971 // they are actually direct calls to eval is determined at run time.
1972 this->CheckPossibleEvalCall(result, scope_);
1973 result = factory()->NewCall(result, args, pos);
1974 if (fni_ != NULL) fni_->RemoveLastFunction();
1978 case Token::PERIOD: {
1979 Consume(Token::PERIOD);
1980 int pos = position();
1981 IdentifierT name = ParseIdentifierName(CHECK_OK);
1982 result = factory()->NewProperty(
1983 result, factory()->NewLiteral(name, pos), pos);
1984 if (fni_ != NULL) this->PushLiteralName(fni_, name);
1995 template <class Traits>
1996 typename ParserBase<Traits>::ExpressionT
1997 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
1999 // ('new')+ MemberExpression
2001 // The grammar for new expressions is pretty warped. We can have several 'new'
2002 // keywords following each other, and then a MemberExpression. When we see '('
2003 // after the MemberExpression, it's associated with the rightmost unassociated
2004 // 'new' to create a NewExpression with arguments. However, a NewExpression
2005 // can also occur without arguments.
2007 // Examples of new expression:
2008 // new foo.bar().baz means (new (foo.bar)()).baz
2009 // new foo()() means (new foo())()
2010 // new new foo()() means (new (new foo())())
2011 // new new foo means new (new foo)
2012 // new new foo() means new (new foo())
2013 // new new foo().bar().baz means (new (new foo()).bar()).baz
2015 if (peek() == Token::NEW) {
2016 Consume(Token::NEW);
2017 int new_pos = position();
2018 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
2019 if (peek() == Token::LPAREN) {
2020 // NewExpression with arguments.
2021 typename Traits::Type::ExpressionList args =
2022 this->ParseArguments(CHECK_OK);
2023 result = factory()->NewCallNew(result, args, new_pos);
2024 // The expression can still continue with . or [ after the arguments.
2025 result = this->ParseMemberExpressionContinuation(result, CHECK_OK);
2028 // NewExpression without arguments.
2029 return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
2032 // No 'new' keyword.
2033 return this->ParseMemberExpression(ok);
2037 template <class Traits>
2038 typename ParserBase<Traits>::ExpressionT
2039 ParserBase<Traits>::ParseMemberExpression(bool* ok) {
2040 // MemberExpression ::
2041 // (PrimaryExpression | FunctionLiteral)
2042 // ('[' Expression ']' | '.' Identifier | Arguments)*
2044 // The '[' Expression ']' and '.' Identifier parts are parsed by
2045 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
2048 // Parse the initial primary or function expression.
2049 ExpressionT result = this->EmptyExpression();
2050 if (peek() == Token::FUNCTION) {
2051 Consume(Token::FUNCTION);
2052 int function_token_position = position();
2053 bool is_generator = allow_generators() && Check(Token::MUL);
2055 bool is_strict_reserved_name = false;
2056 Scanner::Location function_name_location = Scanner::Location::invalid();
2057 FunctionLiteral::FunctionType function_type =
2058 FunctionLiteral::ANONYMOUS_EXPRESSION;
2059 if (peek_any_identifier()) {
2060 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
2062 function_name_location = scanner()->location();
2063 function_type = FunctionLiteral::NAMED_EXPRESSION;
2065 result = this->ParseFunctionLiteral(name,
2066 function_name_location,
2067 is_strict_reserved_name,
2069 function_token_position,
2073 result = ParsePrimaryExpression(CHECK_OK);
2076 result = ParseMemberExpressionContinuation(result, CHECK_OK);
2081 template <class Traits>
2082 typename ParserBase<Traits>::ExpressionT
2083 ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
2085 // Parses this part of MemberExpression:
2086 // ('[' Expression ']' | '.' Identifier)*
2089 case Token::LBRACK: {
2090 Consume(Token::LBRACK);
2091 int pos = position();
2092 ExpressionT index = this->ParseExpression(true, CHECK_OK);
2093 expression = factory()->NewProperty(expression, index, pos);
2095 this->PushPropertyName(fni_, index);
2097 Expect(Token::RBRACK, CHECK_OK);
2100 case Token::PERIOD: {
2101 Consume(Token::PERIOD);
2102 int pos = position();
2103 IdentifierT name = ParseIdentifierName(CHECK_OK);
2104 expression = factory()->NewProperty(
2105 expression, factory()->NewLiteral(name, pos), pos);
2107 this->PushLiteralName(fni_, name);
2116 return this->EmptyExpression();
2121 #undef CHECK_OK_CUSTOM
2124 template <typename Traits>
2125 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
2126 Token::Value property,
2130 if (property == Token::NUMBER) {
2131 old = scanner()->FindNumber(&finder_, type);
2133 old = scanner()->FindSymbol(&finder_, type);
2135 PropertyKind old_type = static_cast<PropertyKind>(old);
2136 if (HasConflict(old_type, type)) {
2137 if (IsDataDataConflict(old_type, type)) {
2138 // Both are data properties.
2139 if (strict_mode_ == SLOPPY) return;
2140 parser()->ReportMessageAt(scanner()->location(),
2141 "strict_duplicate_property");
2142 } else if (IsDataAccessorConflict(old_type, type)) {
2143 // Both a data and an accessor property with the same name.
2144 parser()->ReportMessageAt(scanner()->location(),
2145 "accessor_data_property");
2147 ASSERT(IsAccessorAccessorConflict(old_type, type));
2148 // Both accessors of the same type.
2149 parser()->ReportMessageAt(scanner()->location(),
2150 "accessor_get_set");
2159 #endif // V8_PREPARSER_H