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