V8 Project
preparser.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_PREPARSER_H
6 #define V8_PREPARSER_H
7 
8 #include "src/v8.h"
9 
10 #include "src/bailout-reason.h"
11 #include "src/func-name-inferrer.h"
12 #include "src/hashmap.h"
13 #include "src/scanner.h"
14 #include "src/scopes.h"
15 #include "src/token.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 // Common base class shared between parser and pre-parser. Traits encapsulate
21 // the differences between Parser and PreParser:
22 
23 // - Return types: For example, Parser functions return Expression* and
24 // PreParser functions return PreParserExpression.
25 
26 // - Creating parse tree nodes: Parser generates an AST during the recursive
27 // descent. PreParser doesn't create a tree. Instead, it passes around minimal
28 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain
29 // just enough data for the upper layer functions. PreParserFactory is
30 // responsible for creating these dummy objects. It provides a similar kind of
31 // interface as AstNodeFactory, so ParserBase doesn't need to care which one is
32 // used.
33 
34 // - Miscellaneous other tasks interleaved with the recursive descent. For
35 // example, Parser keeps track of which function literals should be marked as
36 // pretenured, and PreParser doesn't care.
37 
38 // The traits are expected to contain the following typedefs:
39 // struct Traits {
40 // // In particular...
41 // struct Type {
42 // // Used by FunctionState and BlockState.
43 // typedef Scope;
44 // typedef GeneratorVariable;
45 // typedef Zone;
46 // // Return types for traversing functions.
47 // typedef Identifier;
48 // typedef Expression;
49 // typedef FunctionLiteral;
50 // typedef ClassLiteral;
51 // typedef ObjectLiteralProperty;
52 // typedef Literal;
53 // typedef ExpressionList;
54 // typedef PropertyList;
55 // // For constructing objects returned by the traversing functions.
56 // typedef Factory;
57 // };
58 // // ...
59 // };
60 
61 template <typename Traits>
62 class ParserBase : public Traits {
63  public:
64  // Shorten type names defined by Traits.
65  typedef typename Traits::Type::Expression ExpressionT;
66  typedef typename Traits::Type::Identifier IdentifierT;
67  typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
68  typedef typename Traits::Type::Literal LiteralT;
69  typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
70 
71  ParserBase(Scanner* scanner, uintptr_t stack_limit, v8::Extension* extension,
72  ParserRecorder* log, typename Traits::Type::Zone* zone,
74  typename Traits::Type::Parser this_object)
75  : Traits(this_object),
77  scope_(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),
90  zone_(zone),
92 
93  // Getters that indicate whether certain syntactical constructs are
94  // allowed to be parsed by this instance of the parser.
95  bool allow_lazy() const { return allow_lazy_; }
98  bool allow_modules() const { return scanner()->HarmonyModules(); }
99  bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
101  return scanner()->HarmonyNumericLiterals();
102  }
103  bool allow_classes() const { return scanner()->HarmonyClasses(); }
106  }
107 
108  // Setters that determine whether certain syntactical constructs are
109  // allowed to be parsed by this instance of the parser.
110  void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
111  void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
112  void set_allow_arrow_functions(bool allow) { allow_arrow_functions_ = allow; }
113  void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
114  void set_allow_harmony_scoping(bool allow) {
115  scanner()->SetHarmonyScoping(allow);
116  }
119  }
120  void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); }
123  }
124 
125  protected:
126  friend class Traits::Checkpoint;
127 
131  };
132 
133  enum Mode {
136  };
137 
138  class CheckpointBase;
139  class ObjectLiteralChecker;
140 
141  // ---------------------------------------------------------------------------
142  // FunctionState and BlockState together implement the parser's scope stack.
143  // The parser's current scope is in scope_. BlockState and FunctionState
144  // constructors push on the scope stack and the destructors pop. They are also
145  // used to hold the parser's per-function and per-block state.
146  class BlockState BASE_EMBEDDED {
147  public:
148  BlockState(typename Traits::Type::Scope** scope_stack,
149  typename Traits::Type::Scope* scope)
150  : scope_stack_(scope_stack),
151  outer_scope_(*scope_stack),
152  scope_(scope) {
153  *scope_stack_ = scope_;
154  }
155  ~BlockState() { *scope_stack_ = outer_scope_; }
156 
157  private:
158  typename Traits::Type::Scope** scope_stack_;
159  typename Traits::Type::Scope* outer_scope_;
160  typename Traits::Type::Scope* scope_;
161  };
162 
163  class FunctionState BASE_EMBEDDED {
164  public:
165  FunctionState(FunctionState** function_state_stack,
166  typename Traits::Type::Scope** scope_stack,
167  typename Traits::Type::Scope* scope,
168  typename Traits::Type::Zone* zone = NULL,
169  AstValueFactory* ast_value_factory = NULL,
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,
178 
180  return next_materialized_literal_index_++;
181  }
183  return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
184  }
185 
186  int NextHandlerIndex() { return next_handler_index_++; }
187  int handler_count() { return next_handler_index_; }
188 
189  void AddProperty() { expected_property_count_++; }
190  int expected_property_count() { return expected_property_count_; }
191 
192  void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
193  bool is_generator() const { return is_generator_; }
194 
196  typename Traits::Type::GeneratorVariable* variable) {
197  DCHECK(variable != NULL);
198  DCHECK(!is_generator());
199  generator_object_variable_ = variable;
200  is_generator_ = true;
201  }
202  typename Traits::Type::GeneratorVariable* generator_object_variable()
203  const {
204  return generator_object_variable_;
205  }
206 
207  typename Traits::Type::Factory* factory() { return &factory_; }
208 
209  private:
210  // Used to assign an index to each literal that needs materialization in
211  // the function. Includes regexp literals, and boilerplate for object and
212  // array literals.
214 
215  // Used to assign a per-function index to try and catch handlers.
217 
218  // Properties count estimation.
220 
221  // Whether the function is a 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.
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.
234  typename Traits::Type::Zone* extra_param_;
235  typename Traits::Type::Factory factory_;
236 
237  friend class ParserTraits;
238  friend class CheckpointBase;
239  };
240 
241  // Annoyingly, arrow functions first parse as comma expressions, then when we
242  // see the => we have to go back and reinterpret the arguments as being formal
243  // parameters. To do so we need to reset some of the parser state back to
244  // what it was before the arguments were first seen.
245  class CheckpointBase BASE_EMBEDDED {
246  public:
247  explicit CheckpointBase(ParserBase* parser) {
249  next_materialized_literal_index_ =
250  function_state_->next_materialized_literal_index_;
251  next_handler_index_ = function_state_->next_handler_index_;
252  expected_property_count_ = function_state_->expected_property_count_;
253  }
254 
255  void Restore() {
256  function_state_->next_materialized_literal_index_ =
257  next_materialized_literal_index_;
258  function_state_->next_handler_index_ = next_handler_index_;
259  function_state_->expected_property_count_ = expected_property_count_;
260  }
261 
262  private:
263  FunctionState* function_state_;
264  int next_materialized_literal_index_;
265  int next_handler_index_;
266  int expected_property_count_;
267  };
268 
269  class ParsingModeScope BASE_EMBEDDED {
270  public:
272  : parser_(parser),
273  old_mode_(parser->mode()) {
274  parser_->mode_ = mode;
275  }
277  parser_->mode_ = old_mode_;
278  }
279 
280  private:
283  };
284 
285  Scanner* scanner() const { return scanner_; }
286  int position() { return scanner_->location().beg_pos; }
288  bool stack_overflow() const { return stack_overflow_; }
290  Mode mode() const { return mode_; }
291  typename Traits::Type::Zone* zone() const { return zone_; }
293 
295  if (stack_overflow_) return Token::ILLEGAL;
296  return scanner()->peek();
297  }
298 
300  if (stack_overflow_) return Token::ILLEGAL;
301  {
303  // Any further calls to Next or peek will return the illegal token.
304  // The current call must return the next token, which might already
305  // have been peek'ed.
306  stack_overflow_ = true;
307  }
308  }
309  return scanner()->Next();
310  }
311 
312  void Consume(Token::Value token) {
313  Token::Value next = Next();
314  USE(next);
315  USE(token);
316  DCHECK(next == token);
317  }
318 
319  bool Check(Token::Value token) {
320  Token::Value next = peek();
321  if (next == token) {
322  Consume(next);
323  return true;
324  }
325  return false;
326  }
327 
328  void Expect(Token::Value token, bool* ok) {
329  Token::Value next = Next();
330  if (next != token) {
331  ReportUnexpectedToken(next);
332  *ok = false;
333  }
334  }
335 
336  void ExpectSemicolon(bool* ok) {
337  // Check for automatic semicolon insertion according to
338  // the rules given in ECMA-262, section 7.9, page 21.
339  Token::Value tok = peek();
340  if (tok == Token::SEMICOLON) {
341  Next();
342  return;
343  }
344  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
345  tok == Token::RBRACE ||
346  tok == Token::EOS) {
347  return;
348  }
349  Expect(Token::SEMICOLON, ok);
350  }
351 
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 
362  if (peek() == Token::IDENTIFIER &&
363  scanner()->is_next_contextual_keyword(keyword)) {
364  Consume(Token::IDENTIFIER);
365  return true;
366  }
367  return false;
368  }
369 
370  void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
371  Expect(Token::IDENTIFIER, ok);
372  if (!*ok) return;
373  if (!scanner()->is_literal_contextual_keyword(keyword)) {
374  ReportUnexpectedToken(scanner()->current_token());
375  *ok = false;
376  }
377  }
378 
379  // Checks whether an octal literal was last seen between beg_pos and end_pos.
380  // If so, reports an error. Only called for strict mode.
381  void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
383  if (octal.IsValid() && beg_pos <= octal.beg_pos &&
384  octal.end_pos <= end_pos) {
385  ReportMessageAt(octal, "strict_octal_literal");
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.
395  IdentifierT function_name,
396  bool function_name_is_strict_reserved,
397  const Scanner::Location& function_name_loc,
398  const Scanner::Location& eval_args_error_loc,
399  const Scanner::Location& dupe_error_loc,
400  const Scanner::Location& reserved_loc,
401  bool* ok) {
402  if (this->IsEvalOrArguments(function_name)) {
403  Traits::ReportMessageAt(function_name_loc, "strict_eval_arguments");
404  *ok = false;
405  return;
406  }
407  if (function_name_is_strict_reserved) {
408  Traits::ReportMessageAt(function_name_loc, "unexpected_strict_reserved");
409  *ok = false;
410  return;
411  }
412  if (eval_args_error_loc.IsValid()) {
413  Traits::ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
414  *ok = false;
415  return;
416  }
417  if (dupe_error_loc.IsValid()) {
418  Traits::ReportMessageAt(dupe_error_loc, "strict_param_dupe");
419  *ok = false;
420  return;
421  }
422  if (reserved_loc.IsValid()) {
423  Traits::ReportMessageAt(reserved_loc, "unexpected_strict_reserved");
424  *ok = false;
425  return;
426  }
427  }
428 
429  // Determine precedence of given token.
430  static int Precedence(Token::Value token, bool accept_IN) {
431  if (token == Token::IN && !accept_IN)
432  return 0; // 0 precedence will terminate binary expression parsing
433  return Token::Precedence(token);
434  }
435 
436  typename Traits::Type::Factory* factory() {
437  return function_state_->factory();
438  }
439 
440  StrictMode strict_mode() { return scope_->strict_mode(); }
441  bool is_generator() const { return function_state_->is_generator(); }
442 
443  // Report syntax errors.
444  void ReportMessage(const char* message, const char* arg = NULL,
445  bool is_reference_error = false) {
446  Scanner::Location source_location = scanner()->location();
447  Traits::ReportMessageAt(source_location, message, arg, is_reference_error);
448  }
449 
450  void ReportMessageAt(Scanner::Location location, const char* message,
451  bool is_reference_error = false) {
452  Traits::ReportMessageAt(location, message,
453  reinterpret_cast<const char*>(NULL),
454  is_reference_error);
455  }
456 
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;").
468  bool* ok);
469  // Parses an identifier or a strict mode future reserved word, and indicate
470  // whether it is strict mode future reserved.
472  bool* is_strict_reserved,
473  bool* ok);
475  // Parses an identifier and determines whether or not it is 'get' or 'set'.
477  bool* is_set,
478  bool* ok);
479 
480  ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok);
481 
483  ExpressionT ParseExpression(bool accept_IN, bool* ok);
485  IdentifierT ParsePropertyName(bool* is_get, bool* is_set, bool* is_static,
486  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);
494  ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
495  ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
502  bool* ok);
504  bool* ok);
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.
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.
529  kNone = 0,
530  // Bit patterns representing different object literal property types.
534  // Helper constants.
535  kValueFlag = 4
536  };
537 
538  // Validation per ECMA 262 - 11.1.5 "Object Initializer".
540  public:
542  : parser_(parser),
543  finder_(scanner()->unicode_cache()),
545 
546  void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
547 
548  private:
549  ParserBase* parser() const { return parser_; }
550  Scanner* scanner() const { return parser_->scanner(); }
551 
552  // Checks the type of conflict based on values coming from PropertyType.
553  bool HasConflict(PropertyKind type1, PropertyKind type2) {
554  return (type1 & type2) != 0;
555  }
557  return ((type1 & type2) & kValueFlag) != 0;
558  }
560  return ((type1 ^ type2) & kValueFlag) != 0;
561  }
563  return ((type1 | type2) & kValueFlag) == 0;
564  }
565 
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.
576 
577  typename Traits::Type::Scope* scope_; // Scope stack.
578  FunctionState* function_state_; // Function state stack.
584 
585  private:
588 
593 
594  typename Traits::Type::Zone* zone_; // Only used by Parser.
596 };
597 
598 
600  public:
604  }
607  }
610  }
613  }
616  }
619  }
622  }
625  }
628  }
629  bool IsEval() const { return type_ == kEvalIdentifier; }
630  bool IsArguments() const { return type_ == kArgumentsIdentifier; }
631  bool IsYield() const { return type_ == kYieldIdentifier; }
632  bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
633  bool IsConstructor() const { return type_ == kConstructorIdentifier; }
634  bool IsEvalOrArguments() const {
636  }
638  bool IsFutureStrictReserved() const {
640  }
641  bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; }
642 
643  // Allow identifier->name()[->length()] to work. The preparser
644  // does not need the actual positions/lengths of the identifiers.
645  const PreParserIdentifier* operator->() const { return this; }
646  const PreParserIdentifier raw_name() const { return *this; }
647 
648  int position() const { return 0; }
649  int length() const { return 0; }
650 
651  private:
652  enum Type {
662  };
663  explicit PreParserIdentifier(Type type) : 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.
677  public:
680  }
681 
684  (id.type_ << kIdentifierShift));
685  }
686 
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;
695  }
696 
698  // Any expression for which IsValidArrowParamList() returns true
699  // will work here.
701  }
702 
705  }
706 
709  }
710 
713  }
714 
717  }
718 
721  }
722 
725  }
726 
729  }
730 
731  bool IsIdentifier() const { return (code_ & kTypeMask) == kTypeIdentifier; }
732 
734  DCHECK(IsIdentifier());
735  return PreParserIdentifier(
737  }
738 
739  bool IsStringLiteral() const {
740  return (code_ & kTypeMask) == kTypeStringLiteral;
741  }
742 
743  bool IsUseStrictLiteral() const {
745  }
746 
747  bool IsThis() const { return (code_ & kThisExpression) == kThisExpression; }
748 
749  bool IsThisProperty() const {
751  }
752 
753  bool IsProperty() const {
756  }
757 
758  bool IsCall() const { return (code_ & kCallExpression) == kCallExpression; }
759 
761  return IsIdentifier() || IsProperty();
762  }
763 
764  bool IsValidArrowParamList() const {
767  }
768 
769  // At the moment PreParser doesn't track these expression types.
770  bool IsFunctionLiteral() const { return false; }
771  bool IsCallNew() const { return false; }
772 
774 
775  bool IsBinaryOperation() const {
776  return (code_ & kTypeMask) == kTypeBinaryOperation;
777  }
778 
779  bool is_parenthesized() const {
780  return (code_ & kParenthesizedExpression) != 0;
781  }
782 
786  }
787 
788  // Dummy implementation for making expression->somefunc() work in both Parser
789  // and PreParser.
790  PreParserExpression* operator->() { return this; }
791 
792  // More dummy implementations of things PreParser doesn't need to track:
793  void set_index(int index) {} // For YieldExpressions
795 
796  int position() const { return RelocInfo::kNoPosition; }
798  void set_ast_properties(int* ast_properties) {}
799  void set_dont_optimize_reason(BailoutReason dont_optimize_reason) {}
800 
801  bool operator==(const PreParserExpression& other) const {
802  return code_ == other.code_;
803  }
804  bool operator!=(const PreParserExpression& other) const {
805  return code_ != other.code_;
806  }
807 
808  private:
809  // Least significant 2 bits are used as expression type. The third least
810  // significant bit tracks whether an expression is parenthesized. If the
811  // expression is an identifier or a string literal, the other bits
812  // describe the type/ (see PreParserIdentifier::Type and string literal
813  // constants below). For binary operations, the other bits are flags
814  // which further describe the contents of the expression.
815  enum {
817  kTypeMask = 1 | 2,
820 
821  // Identifiers
822  kTypeIdentifier = 1, // Used to detect labels.
824  kTypeStringLiteral = 2, // Used to detect directive prologue.
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.
834 
835  // Below here applies if neither identifier nor string literal. Reserve the
836  // 2 least significant bits for flags.
837  kThisExpression = (1 << 4),
840  kCallExpression = (4 << 4),
841  kSuperExpression = (5 << 4)
842  };
843 
844  explicit PreParserExpression(int expression_code) : code_(expression_code) {}
845 
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;
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.
867  public:
868  // These functions make list->Add(some_expression) work (and do nothing).
871  void Add(PreParserExpression, void*) { ++length_; }
872  int length() const { return length_; }
873  private:
874  int length_;
875 };
876 
877 
879  public:
882  }
883 
886  }
887 
888  // Creates expression statement from expression.
889  // Preserves being an unparenthesized string literal, possibly
890  // "use strict".
892  PreParserExpression expression) {
893  if (expression.IsUseStrictLiteral()) {
895  }
896  if (expression.IsStringLiteral()) {
898  }
899  return Default();
900  }
901 
904  }
905 
908  }
909 
911  return code_ == kFunctionDeclaration;
912  }
913 
914  private:
915  enum Type {
920  };
921 
922  explicit PreParserStatement(Type code) : code_(code) {}
924 };
925 
926 
927 
928 // PreParserStatementList doesn't actually store the statements because
929 // the PreParser does not need them.
931  public:
932  // These functions make list->Add(some_expression) work as no-ops.
934  PreParserStatementList* operator->() { return this; }
935  void Add(PreParserStatement, void*) {}
936 };
937 
938 
940  public:
941  explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type,
942  void* = NULL)
943  : scope_type_(scope_type) {
944  strict_mode_ = outer_scope ? outer_scope->strict_mode() : SLOPPY;
945  }
946 
947  ScopeType type() { return scope_type_; }
948  StrictMode strict_mode() const { return strict_mode_; }
951 
952  // When PreParser is in use, lazy compilation is already being done,
953  // things cannot get lazier than that.
954  bool AllowsLazyCompilation() const { return false; }
955 
956  void set_start_position(int position) {}
957  void set_end_position(int position) {}
958 
959  bool IsDeclared(const PreParserIdentifier& identifier) const { return false; }
961 
962  // Allow scope->Foo() to work.
963  PreParserScope* operator->() { return this; }
964 
965  private:
968 };
969 
970 
972  public:
973  PreParserFactory(void*, void*, void*) {}
975  int pos) {
977  }
979  int pos) {
981  }
983  PreParserIdentifier js_flags,
984  int literal_index,
985  int pos) {
987  }
989  int literal_index,
990  int pos) {
992  }
994  PreParserExpression value,
995  int pos, bool is_static) {
997  }
999  PreParserExpression value,
1000  bool is_static) {
1002  }
1004  int literal_index,
1005  int boilerplate_properties,
1006  bool has_function,
1007  int pos) {
1009  }
1012  }
1014  PreParserExpression key,
1015  int pos) {
1016  if (obj.IsThis()) {
1018  }
1020  }
1022  PreParserExpression expression,
1023  int pos) {
1025  }
1027  PreParserExpression left,
1028  PreParserExpression right, int pos) {
1029  return PreParserExpression::BinaryOperation(left, op, right);
1030  }
1032  PreParserExpression left,
1033  PreParserExpression right, int pos) {
1035  }
1037  PreParserExpression left,
1038  PreParserExpression right,
1039  int pos) {
1041  }
1043  PreParserExpression expression,
1044  Yield::Kind yield_kind,
1045  int pos) {
1047  }
1049  PreParserExpression then_expression,
1050  PreParserExpression else_expression,
1051  int pos) {
1053  }
1055  bool is_prefix,
1056  PreParserExpression expression,
1057  int pos) {
1059  }
1061  PreParserExpressionList arguments,
1062  int pos) {
1063  return PreParserExpression::Call();
1064  }
1066  PreParserExpressionList arguments,
1067  int pos) {
1069  }
1071  int pos) {
1072  return PreParserStatement::Default();
1073  }
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) {
1085  }
1087  PreParserExpression extends,
1088  PreParserExpression constructor,
1089  PreParserExpressionList properties,
1090  int position) {
1092  }
1093 
1094  // Return the object itself as AstVisitor and implement the needed
1095  // dummy method right in this class.
1096  PreParserFactory* visitor() { return this; }
1097  BailoutReason dont_optimize_reason() { return kNoReason; }
1099  static int dummy = 42;
1100  return &dummy;
1101  }
1102 };
1103 
1104 
1105 class PreParser;
1106 
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.
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;
1125 
1126  // Return types for traversing functions.
1137 
1138  // For constructing objects returned by the traversing functions.
1140  };
1141 
1142  class Checkpoint;
1143 
1144  explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
1145 
1146  // Custom operations executed when FunctionStates are created and
1147  // destructed. (The PreParser doesn't need to do anything.)
1148  template <typename FunctionState>
1149  static void SetUpFunctionState(FunctionState* function_state) {}
1150  template <typename FunctionState>
1151  static void TearDownFunctionState(FunctionState* function_state) {}
1152 
1153  // Helper functions for recursive descent.
1154  static bool IsEvalOrArguments(PreParserIdentifier identifier) {
1155  return identifier.IsEvalOrArguments();
1156  }
1157 
1158  static bool IsPrototype(PreParserIdentifier identifier) {
1159  return identifier.IsPrototype();
1160  }
1161 
1162  static bool IsConstructor(PreParserIdentifier identifier) {
1163  return identifier.IsConstructor();
1164  }
1165 
1166  // Returns true if the expression is of type "this.foo".
1167  static bool IsThisProperty(PreParserExpression expression) {
1168  return expression.IsThisProperty();
1169  }
1170 
1171  static bool IsIdentifier(PreParserExpression expression) {
1172  return expression.IsIdentifier();
1173  }
1174 
1176  return expression.AsIdentifier();
1177  }
1178 
1180  return identifier.IsYield() || identifier.IsFutureStrictReserved();
1181  }
1182 
1184  // PreParser doesn't count boilerplate properties.
1185  return false;
1186  }
1187 
1188  static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
1189  return false;
1190  }
1191 
1192  // Functions for encapsulating the differences between parsing and preparsing;
1193  // operations interleaved with the recursive descent.
1195  // PreParser should not use FuncNameInferrer.
1196  UNREACHABLE();
1197  }
1199  PreParserExpression expression) {
1200  // PreParser should not use FuncNameInferrer.
1201  UNREACHABLE();
1202  }
1204  PreParserExpression expression) {
1205  // PreParser should not use FuncNameInferrer.
1206  UNREACHABLE();
1207  }
1208 
1210  PreParserScope* scope, PreParserExpression property, bool* has_function) {
1211  }
1212 
1215 
1216  // PreParser doesn't need to keep track of eval calls.
1218  PreParserScope* scope) {}
1219 
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 
1229  Token::Value op,
1230  int pos,
1231  PreParserFactory* factory) {
1232  return false;
1233  }
1234 
1236  Token::Value op, int pos,
1237  PreParserFactory* factory) {
1239  }
1240 
1241  PreParserExpression NewThrowReferenceError(const char* type, int pos) {
1243  }
1245  const char* type, Handle<Object> arg, int pos) {
1247  }
1249  const char* type, Handle<Object> arg, int pos) {
1251  }
1252  PreParserScope NewScope(PreParserScope* outer_scope, ScopeType scope_type) {
1253  return PreParserScope(outer_scope, scope_type);
1254  }
1255 
1256  // Reporting errors.
1257  void ReportMessageAt(Scanner::Location location,
1258  const char* message,
1259  const char* arg = NULL,
1260  bool is_reference_error = false);
1261  void ReportMessageAt(int start_pos,
1262  int end_pos,
1263  const char* message,
1264  const char* arg = NULL,
1265  bool is_reference_error = false);
1266 
1267  // "null" return type creators.
1270  }
1273  }
1276  }
1279  }
1282  }
1285  }
1288  }
1290  return PreParserExpressionList();
1291  }
1292 
1293  // Odd-ball literal creators.
1295  PreParserFactory* factory) {
1297  }
1298 
1299  // Producing data during the recursive descent.
1302 
1305  }
1306 
1308  PreParserFactory* factory) {
1309  return PreParserExpression::This();
1310  }
1311 
1313  PreParserFactory* factory) {
1314  return PreParserExpression::Super();
1315  }
1316 
1318  PreParserExpression extends,
1319  PreParserExpression constructor,
1320  PreParserExpressionList properties,
1321  int position,
1322  PreParserFactory* factory) {
1324  }
1325 
1327  Token::Value token, int pos, Scanner* scanner,
1328  PreParserFactory* factory) {
1330  }
1331 
1333  PreParserIdentifier name, int pos, PreParserScope* scope,
1334  PreParserFactory* factory) {
1336  }
1337 
1339  Scanner* scanner,
1340  PreParserFactory* factory = NULL);
1341 
1343  PreParserFactory* factory) {
1345  }
1346 
1348  return PreParserExpressionList();
1349  }
1350 
1352  return PreParserStatementList();
1353  }
1354 
1356  return PreParserExpressionList();
1357  }
1358 
1360  int* materialized_literal_count,
1361  int* expected_property_count, bool* ok) {
1362  UNREACHABLE();
1363  }
1364 
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
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 
1381 
1383 
1384  // Temporary glue; these functions will move to ParserBase.
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:
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:
1414 
1418  };
1419 
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.
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 '}'.
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 
1467  };
1468 
1469  // If a list of variable declarations includes any initializers.
1473  };
1474 
1475 
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);
1488  Statement ParseClassDeclaration(bool* ok);
1489  Statement ParseBlock(bool* ok);
1491  bool* ok);
1493  VariableDeclarationProperties* decl_props,
1494  int* num_decl,
1495  bool* ok);
1497  Statement ParseIfStatement(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);
1509  Expression ParseConditionalExpression(bool accept_IN, bool* ok);
1511  Expression ParseV8Intrinsic(bool* ok);
1512 
1514  int* materialized_literal_count,
1515  int* expected_property_count, bool* ok);
1517  ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
1518  Variable* fvar, Token::Value fvar_init_op,
1519  bool is_generator, bool* ok);
1520 
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 
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 
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>
1555  FunctionState** function_state_stack,
1556  typename Traits::Type::Scope** scope_stack,
1557  typename Traits::Type::Scope* scope, typename Traits::Type::Zone* zone,
1558  AstValueFactory* ast_value_factory, AstNode::IdGen* ast_node_id_gen)
1559  : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
1560  next_handler_index_(0),
1561  expected_property_count_(0),
1562  is_generator_(false),
1563  generator_object_variable_(NULL),
1564  function_state_stack_(function_state_stack),
1565  outer_function_state_(*function_state_stack),
1566  scope_stack_(scope_stack),
1567  outer_scope_(*scope_stack),
1568  ast_node_id_gen_(ast_node_id_gen),
1569  factory_(zone, ast_value_factory, ast_node_id_gen) {
1570  *scope_stack_ = scope;
1571  *function_state_stack = this;
1572  Traits::SetUpFunctionState(this);
1573 }
1574 
1575 
1576 template <class Traits>
1577 ParserBase<Traits>::FunctionState::FunctionState(
1578  FunctionState** function_state_stack,
1579  typename Traits::Type::Scope** scope_stack,
1580  typename Traits::Type::Scope** scope, typename Traits::Type::Zone* zone,
1581  AstValueFactory* ast_value_factory, AstNode::IdGen* ast_node_id_gen)
1582  : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
1583  next_handler_index_(0),
1584  expected_property_count_(0),
1585  is_generator_(false),
1586  generator_object_variable_(NULL),
1587  function_state_stack_(function_state_stack),
1588  outer_function_state_(*function_state_stack),
1589  scope_stack_(scope_stack),
1590  outer_scope_(*scope_stack),
1591  ast_node_id_gen_(ast_node_id_gen),
1592  factory_(zone, ast_value_factory, ast_node_id_gen) {
1593  *scope_stack_ = *scope;
1594  *function_state_stack = this;
1595  Traits::SetUpFunctionState(this);
1596 }
1597 
1598 
1599 template <class Traits>
1600 ParserBase<Traits>::FunctionState::~FunctionState() {
1601  *scope_stack_ = outer_scope_;
1602  *function_state_stack_ = outer_function_state_;
1603  Traits::TearDownFunctionState(this);
1604 }
1605 
1606 
1607 template<class Traits>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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));
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
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>
2048  bool* ok) {
2049  // ObjectLiteral ::
2050  // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
2051 
2052  int pos = peek_position();
2053  typename Traits::Type::PropertyList properties =
2054  this->NewPropertyList(4, zone_);
2055  int number_of_boilerplate_properties = 0;
2056  bool has_function = false;
2057 
2058  ObjectLiteralChecker checker(this, strict_mode());
2059 
2060  Expect(Token::LBRACE, CHECK_OK);
2061 
2062  while (peek() != Token::RBRACE) {
2063  if (fni_ != NULL) fni_->Enter();
2064 
2065  const bool in_class = false;
2066  const bool is_static = false;
2067  ObjectLiteralPropertyT property =
2068  this->ParsePropertyDefinition(&checker, in_class, is_static, CHECK_OK);
2069 
2070  // Mark top-level object literals that contain function literals and
2071  // pretenure the literal so it can be added as a constant function
2072  // property. (Parser only.)
2073  this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property,
2074  &has_function);
2075 
2076  // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
2077  if (this->IsBoilerplateProperty(property)) {
2078  number_of_boilerplate_properties++;
2079  }
2080  properties->Add(property, zone());
2081 
2082  if (peek() != Token::RBRACE) {
2083  // Need {} because of the CHECK_OK macro.
2084  Expect(Token::COMMA, CHECK_OK);
2085  }
2086 
2087  if (fni_ != NULL) {
2088  fni_->Infer();
2089  fni_->Leave();
2090  }
2091  }
2092  Expect(Token::RBRACE, CHECK_OK);
2093 
2094  // Computation of literal_index must happen before pre parse bailout.
2095  int literal_index = function_state_->NextMaterializedLiteralIndex();
2096 
2097  return factory()->NewObjectLiteral(properties,
2098  literal_index,
2099  number_of_boilerplate_properties,
2100  has_function,
2101  pos);
2102 }
2103 
2104 
2105 template <class Traits>
2106 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
2107  bool* ok) {
2108  // Arguments ::
2109  // '(' (AssignmentExpression)*[','] ')'
2110 
2111  typename Traits::Type::ExpressionList result =
2112  this->NewExpressionList(4, zone_);
2113  Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
2114  bool done = (peek() == Token::RPAREN);
2115  while (!done) {
2116  ExpressionT argument = this->ParseAssignmentExpression(
2117  true, CHECK_OK_CUSTOM(NullExpressionList));
2118  result->Add(argument, zone_);
2119  if (result->length() > Code::kMaxArguments) {
2120  ReportMessage("too_many_arguments");
2121  *ok = false;
2122  return this->NullExpressionList();
2123  }
2124  done = (peek() == Token::RPAREN);
2125  if (!done) {
2126  // Need {} because of the CHECK_OK_CUSTOM macro.
2127  Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList));
2128  }
2129  }
2130  Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
2131  return result;
2132 }
2133 
2134 // Precedence = 2
2135 template <class Traits>
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>
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>
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>
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>
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>
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>
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>
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>
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
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>
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>
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();
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>
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>
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>
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
Ignore.
Definition: v8.h:4008
static const int kMaxArguments
Definition: objects.h:5445
static const int kLiteralsPrefixSize
Definition: objects.h:7388
void set_generator_object_variable(typename Traits::Type::GeneratorVariable *variable)
Definition: preparser.h:195
FunctionState(FunctionState **function_state_stack, typename Traits::Type::Scope **scope_stack, typename Traits::Type::Scope *scope, typename Traits::Type::Zone *zone=NULL, AstValueFactory *ast_value_factory=NULL, AstNode::IdGen *ast_node_id_gen=NULL)
BlockState(typename Traits::Type::Scope **scope_stack, typename Traits::Type::Scope *scope)
Definition: preparser.h:148
ParsingModeScope(ParserBase *parser, Mode mode)
Definition: preparser.h:271
Traits::Type::Scope ** scope_stack_
Definition: preparser.h:158
Traits::Type::Factory * factory()
Definition: preparser.h:207
FunctionState(FunctionState **function_state_stack, typename Traits::Type::Scope **scope_stack, typename Traits::Type::Scope **scope, typename Traits::Type::Zone *zone=NULL, AstValueFactory *ast_value_factory=NULL, AstNode::IdGen *ast_node_id_gen=NULL)
Traits::Type::Scope * outer_scope_
Definition: preparser.h:159
void set_is_generator(bool is_generator)
Definition: preparser.h:192
Traits::Type::GeneratorVariable * generator_object_variable() const
Definition: preparser.h:202
ObjectLiteralChecker(ParserBase *parser, StrictMode strict_mode)
Definition: preparser.h:541
bool HasConflict(PropertyKind type1, PropertyKind type2)
Definition: preparser.h:553
void CheckProperty(Token::Value property, PropertyKind type, bool *ok)
Definition: preparser.h:2811
bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2)
Definition: preparser.h:562
bool IsDataDataConflict(PropertyKind type1, PropertyKind type2)
Definition: preparser.h:556
bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2)
Definition: preparser.h:559
v8::Extension * extension_
Definition: preparser.h:579
IdentifierT ParseIdentifierName(bool *ok)
Definition: preparser.h:1684
bool allow_harmony_scoping() const
Definition: preparser.h:99
ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool *ok)
Definition: preparser.h:2278
INLINE(Token::Value peek())
Definition: preparser.h:294
ParserRecorder * log_
Definition: preparser.h:581
ExpressionT ParseClassLiteral(IdentifierT name, Scanner::Location function_name_location, bool name_is_strict_reserved, int pos, bool *ok)
Definition: preparser.h:2721
bool Check(Token::Value token)
Definition: preparser.h:319
static int Precedence(Token::Value token, bool accept_IN)
Definition: preparser.h:430
bool allow_lazy() const
Definition: preparser.h:95
ExpressionT ParsePostfixExpression(bool *ok)
Definition: preparser.h:2372
IdentifierT ParseIdentifierOrStrictReservedWord(bool *is_strict_reserved, bool *ok)
Definition: preparser.h:1664
bool allow_harmony_object_literals() const
Definition: preparser.h:104
ExpressionT ParseObjectLiteral(bool *ok)
Definition: preparser.h:2047
ExpressionT ParseConditionalExpression(bool accept_IN, bool *ok)
Definition: preparser.h:2255
Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT
Definition: preparser.h:69
ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, bool *ok)
Definition: preparser.h:2610
Traits::Type::Scope * scope_
Definition: preparser.h:577
void set_allow_harmony_scoping(bool allow)
Definition: preparser.h:114
IdentifierT ParsePropertyName(bool *is_get, bool *is_set, bool *is_static, bool *ok)
Definition: preparser.h:1919
Traits::Type::Zone * zone() const
Definition: preparser.h:291
void set_allow_lazy(bool allow)
Definition: preparser.h:110
void Expect(Token::Value token, bool *ok)
Definition: preparser.h:328
AstNode::IdGen * ast_node_id_gen() const
Definition: preparser.h:292
Traits::Type::Literal LiteralT
Definition: preparser.h:68
ExpressionT ParseYieldExpression(bool *ok)
Definition: preparser.h:2207
FuncNameInferrer * fni_
Definition: preparser.h:580
void set_allow_arrow_functions(bool allow)
Definition: preparser.h:112
AstNode::IdGen * ast_node_id_gen_
Definition: preparser.h:595
Traits::Type::FunctionLiteral FunctionLiteralT
Definition: preparser.h:67
IdentifierT ParseIdentifierNameOrGetOrSet(bool *is_get, bool *is_set, bool *ok)
Definition: preparser.h:1699
void ReportMessageAt(Scanner::Location location, const char *message, bool is_reference_error=false)
Definition: preparser.h:450
bool allow_natives_syntax() const
Definition: preparser.h:96
IdentifierT ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool *ok)
Definition: preparser.h:1637
Traits::Type::ExpressionList ParseArguments(bool *ok)
Definition: preparser.h:2106
void CheckOctalLiteral(int beg_pos, int end_pos, bool *ok)
Definition: preparser.h:381
Traits::Type::Expression ExpressionT
Definition: preparser.h:65
StrictMode strict_mode()
Definition: preparser.h:440
bool is_generator() const
Definition: preparser.h:441
void set_allow_modules(bool allow)
Definition: preparser.h:113
bool CheckContextualKeyword(Vector< const char > keyword)
Definition: preparser.h:361
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)
Definition: preparser.h:71
ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker *checker, bool in_class, bool is_static, bool *ok)
Definition: preparser.h:1942
void set_allow_harmony_numeric_literals(bool allow)
Definition: preparser.h:117
ExpressionT ParseArrayLiteral(bool *ok)
Definition: preparser.h:1888
void set_allow_harmony_object_literals(bool allow)
Definition: preparser.h:121
void set_allow_classes(bool allow)
Definition: preparser.h:120
ExpressionT ParseAssignmentExpression(bool accept_IN, bool *ok)
Definition: preparser.h:2137
bool stack_overflow() const
Definition: preparser.h:288
void ExpectSemicolon(bool *ok)
Definition: preparser.h:336
ExpressionT CheckAndRewriteReferenceExpression(ExpressionT expression, Scanner::Location location, const char *message, bool *ok)
Definition: preparser.h:2782
void ReportMessage(const char *message, const char *arg=NULL, bool is_reference_error=false)
Definition: preparser.h:444
Traits::Type::Identifier IdentifierT
Definition: preparser.h:66
ExpressionT ParseExpression(bool accept_IN, bool *ok)
Definition: preparser.h:1870
INLINE(Token::Value Next())
Definition: preparser.h:299
ExpressionT ParseUnaryExpression(bool *ok)
Definition: preparser.h:2322
ExpressionT ParseMemberWithNewPrefixesExpression(bool *ok)
Definition: preparser.h:2468
bool allow_modules() const
Definition: preparser.h:98
Scanner * scanner() const
Definition: preparser.h:285
FunctionState * function_state_
Definition: preparser.h:578
bool allow_arrow_functions() const
Definition: preparser.h:97
void 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)
Definition: preparser.h:394
void set_allow_natives_syntax(bool allow)
Definition: preparser.h:111
bool allow_harmony_numeric_literals() const
Definition: preparser.h:100
void ExpectContextualKeyword(Vector< const char > keyword, bool *ok)
Definition: preparser.h:370
ExpressionT ParsePrimaryExpression(bool *ok)
Definition: preparser.h:1750
void Consume(Token::Value token)
Definition: preparser.h:312
friend class Traits::Checkpoint
Definition: preparser.h:126
Traits::Type::Factory * factory()
Definition: preparser.h:436
void ReportUnexpectedToken(Token::Value token)
Definition: preparser.h:1608
ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, bool *ok)
Definition: preparser.h:2571
ExpressionT ParseRegExpLiteral(bool seen_equal, bool *ok)
Definition: preparser.h:1710
ExpressionT ParseMemberExpression(bool *ok)
Definition: preparser.h:2515
Traits::Type::Zone * zone_
Definition: preparser.h:594
bool allow_classes() const
Definition: preparser.h:103
ExpressionT ParseLeftHandSideExpression(bool *ok)
Definition: preparser.h:2397
void Add(PreParserExpression, void *)
Definition: preparser.h:871
PreParserExpressionList * operator->()
Definition: preparser.h:870
static PreParserExpression ThisProperty()
Definition: preparser.h:719
static PreParserExpression FromIdentifier(PreParserIdentifier id)
Definition: preparser.h:682
static PreParserExpression UseStrictStringLiteral()
Definition: preparser.h:707
bool IsValidReferenceExpression() const
Definition: preparser.h:760
void set_function_token_position(int position)
Definition: preparser.h:797
void set_dont_optimize_reason(BailoutReason dont_optimize_reason)
Definition: preparser.h:799
static PreParserExpression BinaryOperation(PreParserExpression left, Token::Value op, PreParserExpression right)
Definition: preparser.h:687
static PreParserExpression Call()
Definition: preparser.h:727
static PreParserExpression Super()
Definition: preparser.h:715
static PreParserExpression This()
Definition: preparser.h:711
static PreParserExpression Property()
Definition: preparser.h:723
bool operator==(const PreParserExpression &other) const
Definition: preparser.h:801
PreParserExpression * operator->()
Definition: preparser.h:790
PreParserExpression(int expression_code)
Definition: preparser.h:844
static PreParserExpression Default()
Definition: preparser.h:678
static PreParserExpression EmptyArrowParamList()
Definition: preparser.h:697
static PreParserExpression StringLiteral()
Definition: preparser.h:703
bool operator!=(const PreParserExpression &other) const
Definition: preparser.h:804
PreParserIdentifier AsIdentifier() const
Definition: preparser.h:733
void set_ast_properties(int *ast_properties)
Definition: preparser.h:798
PreParserExpression AsFunctionLiteral()
Definition: preparser.h:773
PreParserFactory(void *, void *, void *)
Definition: preparser.h:973
PreParserExpression NewProperty(PreParserExpression obj, PreParserExpression key, int pos)
Definition: preparser.h:1013
PreParserExpression NewYield(PreParserExpression generator_object, PreParserExpression expression, Yield::Kind yield_kind, int pos)
Definition: preparser.h:1042
PreParserExpression NewCompareOperation(Token::Value op, PreParserExpression left, PreParserExpression right, int pos)
Definition: preparser.h:1031
PreParserExpression NewAssignment(Token::Value op, PreParserExpression left, PreParserExpression right, int pos)
Definition: preparser.h:1036
PreParserStatement NewReturnStatement(PreParserExpression expression, int pos)
Definition: preparser.h:1070
PreParserExpression NewCallNew(PreParserExpression expression, PreParserExpressionList arguments, int pos)
Definition: preparser.h:1065
PreParserExpression NewBinaryOperation(Token::Value op, PreParserExpression left, PreParserExpression right, int pos)
Definition: preparser.h:1026
PreParserExpression NewNumberLiteral(double number, int pos)
Definition: preparser.h:978
PreParserExpression NewVariableProxy(void *variable)
Definition: preparser.h:1010
BailoutReason dont_optimize_reason()
Definition: preparser.h:1097
PreParserExpression 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)
Definition: preparser.h:1074
PreParserExpression NewObjectLiteralProperty(bool is_getter, PreParserExpression value, int pos, bool is_static)
Definition: preparser.h:993
PreParserExpression NewObjectLiteralProperty(PreParserExpression key, PreParserExpression value, bool is_static)
Definition: preparser.h:998
PreParserExpression NewStringLiteral(PreParserIdentifier identifier, int pos)
Definition: preparser.h:974
PreParserExpression NewCall(PreParserExpression expression, PreParserExpressionList arguments, int pos)
Definition: preparser.h:1060
PreParserExpression NewObjectLiteral(PreParserExpressionList properties, int literal_index, int boilerplate_properties, bool has_function, int pos)
Definition: preparser.h:1003
PreParserFactory * visitor()
Definition: preparser.h:1096
PreParserExpression NewConditional(PreParserExpression condition, PreParserExpression then_expression, PreParserExpression else_expression, int pos)
Definition: preparser.h:1048
PreParserExpression NewUnaryOperation(Token::Value op, PreParserExpression expression, int pos)
Definition: preparser.h:1021
PreParserExpression NewArrayLiteral(PreParserExpressionList values, int literal_index, int pos)
Definition: preparser.h:988
PreParserExpression NewClassLiteral(PreParserIdentifier name, PreParserExpression extends, PreParserExpression constructor, PreParserExpressionList properties, int position)
Definition: preparser.h:1086
PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, PreParserIdentifier js_flags, int literal_index, int pos)
Definition: preparser.h:982
PreParserExpression NewCountOperation(Token::Value op, bool is_prefix, PreParserExpression expression, int pos)
Definition: preparser.h:1054
static PreParserIdentifier Eval()
Definition: preparser.h:605
static PreParserIdentifier Arguments()
Definition: preparser.h:608
static PreParserIdentifier Prototype()
Definition: preparser.h:623
static PreParserIdentifier FutureStrictReserved()
Definition: preparser.h:614
static PreParserIdentifier FutureReserved()
Definition: preparser.h:611
const PreParserIdentifier * operator->() const
Definition: preparser.h:645
const PreParserIdentifier raw_name() const
Definition: preparser.h:646
static PreParserIdentifier Let()
Definition: preparser.h:617
static PreParserIdentifier Default()
Definition: preparser.h:602
static PreParserIdentifier Constructor()
Definition: preparser.h:626
static PreParserIdentifier Yield()
Definition: preparser.h:620
StrictMode strict_mode() const
Definition: preparser.h:948
void set_end_position(int position)
Definition: preparser.h:957
void set_start_position(int position)
Definition: preparser.h:956
void SetScopeName(PreParserIdentifier name)
Definition: preparser.h:950
PreParserScope * operator->()
Definition: preparser.h:963
void SetStrictMode(StrictMode strict_mode)
Definition: preparser.h:949
void DeclareParameter(const PreParserIdentifier &identifier, VariableMode)
Definition: preparser.h:960
bool IsDeclared(const PreParserIdentifier &identifier) const
Definition: preparser.h:959
PreParserScope(PreParserScope *outer_scope, ScopeType scope_type, void *=NULL)
Definition: preparser.h:941
bool AllowsLazyCompilation() const
Definition: preparser.h:954
void Add(PreParserStatement, void *)
Definition: preparser.h:935
PreParserStatementList * operator->()
Definition: preparser.h:934
static PreParserStatement FunctionDeclaration()
Definition: preparser.h:884
static PreParserStatement Default()
Definition: preparser.h:880
static PreParserStatement ExpressionStatement(PreParserExpression expression)
Definition: preparser.h:891
static PreParserExpression EmptyLiteral()
Definition: preparser.h:1280
static PreParserStatementList NewStatementList(int size, void *zone)
Definition: preparser.h:1351
PreParserIdentifier GetNumberAsSymbol(Scanner *scanner)
Definition: preparser.cc:91
PreParserExpression GetIterator(PreParserExpression iterable, PreParserFactory *factory)
Definition: preparser.h:1342
static PreParserExpression MarkExpressionAsAssigned(PreParserExpression expression)
Definition: preparser.h:1220
static PreParserIdentifier GetNextSymbol(Scanner *scanner)
Definition: preparser.h:1303
void CheckConflictingVarDeclarations(PreParserScope scope, bool *ok)
Definition: preparser.h:1382
PreParserExpression ExpressionFromString(int pos, Scanner *scanner, PreParserFactory *factory=NULL)
Definition: preparser.cc:96
static void PushLiteralName(FuncNameInferrer *fni, PreParserIdentifier id)
Definition: preparser.h:1194
void SkipLazyFunctionBody(PreParserIdentifier function_name, int *materialized_literal_count, int *expected_property_count, bool *ok)
Definition: preparser.h:1359
static bool IsBoilerplateProperty(PreParserExpression property)
Definition: preparser.h:1183
static void InferFunctionName(FuncNameInferrer *fni, PreParserExpression expression)
Definition: preparser.h:1203
static PreParserExpression ExpressionFromIdentifier(PreParserIdentifier name, int pos, PreParserScope *scope, PreParserFactory *factory)
Definition: preparser.h:1332
PreParserStatementList ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, Variable *fvar, Token::Value fvar_init_op, bool is_generator, bool *ok)
Definition: preparser.h:1545
PreParserScope NewScope(PreParserScope *outer_scope, ScopeType scope_type)
Definition: preparser.h:1252
PreParserExpression ParseV8Intrinsic(bool *ok)
Definition: preparser.cc:105
static PreParserExpression EmptyArrowParamList()
Definition: preparser.h:1277
static PreParserIdentifier EmptyIdentifier()
Definition: preparser.h:1268
static PreParserExpression ExpressionFromLiteral(Token::Value token, int pos, Scanner *scanner, PreParserFactory *factory)
Definition: preparser.h:1326
bool ShortcutNumericLiteralBinaryExpression(PreParserExpression *x, PreParserExpression y, Token::Value op, int pos, PreParserFactory *factory)
Definition: preparser.h:1227
static PreParserExpression ThisExpression(PreParserScope *scope, PreParserFactory *factory)
Definition: preparser.h:1307
static AstValueFactory * ast_value_factory()
Definition: preparser.h:1380
static void CheckPossibleEvalCall(PreParserExpression expression, PreParserScope *scope)
Definition: preparser.h:1217
PreParserExpression ParseFunctionLiteral(PreParserIdentifier name, Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind, int function_token_position, FunctionLiteral::FunctionType type, FunctionLiteral::ArityRestriction arity_restriction, bool *ok)
Definition: preparser.cc:110
PreParserExpression NewThrowSyntaxError(const char *type, Handle< Object > arg, int pos)
Definition: preparser.h:1244
PreParserExpression NewThrowTypeError(const char *type, Handle< Object > arg, int pos)
Definition: preparser.h:1248
static bool IsThisProperty(PreParserExpression expression)
Definition: preparser.h:1167
static PreParserIdentifier EmptyIdentifierString()
Definition: preparser.h:1271
static PreParserExpression EmptyObjectLiteralProperty()
Definition: preparser.h:1283
static PreParserExpressionList NewPropertyList(int size, void *zone)
Definition: preparser.h:1355
static PreParserExpressionList NewExpressionList(int size, void *zone)
Definition: preparser.h:1347
PreParserIdentifier GetSymbol(Scanner *scanner)
Definition: preparser.cc:64
static PreParserExpression GetLiteralTheHole(int position, PreParserFactory *factory)
Definition: preparser.h:1294
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(PreParserScope *scope, PreParserExpression property, bool *has_function)
Definition: preparser.h:1209
static bool IsIdentifier(PreParserExpression expression)
Definition: preparser.h:1171
PreParserTraits(PreParser *pre_parser)
Definition: preparser.h:1144
static void PushPropertyName(FuncNameInferrer *fni, PreParserExpression expression)
Definition: preparser.h:1198
static PreParserExpression EmptyFunctionLiteral()
Definition: preparser.h:1286
static bool IsConstructor(PreParserIdentifier identifier)
Definition: preparser.h:1162
static void SetUpFunctionState(FunctionState *function_state)
Definition: preparser.h:1149
static PreParserExpression EmptyExpression()
Definition: preparser.h:1274
static bool IsPrototype(PreParserIdentifier identifier)
Definition: preparser.h:1158
static PreParserExpressionList NullExpressionList()
Definition: preparser.h:1289
PreParserExpression BuildUnaryExpression(PreParserExpression expression, Token::Value op, int pos, PreParserFactory *factory)
Definition: preparser.h:1235
void ReportMessageAt(Scanner::Location location, const char *message, const char *arg=NULL, bool is_reference_error=false)
Definition: preparser.cc:42
static void CheckAssigningFunctionLiteralToProperty(PreParserExpression left, PreParserExpression right)
Definition: preparser.h:1213
static bool IsArrayIndex(PreParserIdentifier string, uint32_t *index)
Definition: preparser.h:1188
static PreParserIdentifier AsIdentifier(PreParserExpression expression)
Definition: preparser.h:1175
static PreParserExpression ClassLiteral(PreParserIdentifier name, PreParserExpression extends, PreParserExpression constructor, PreParserExpressionList properties, int position, PreParserFactory *factory)
Definition: preparser.h:1317
static PreParserExpression SuperReference(PreParserScope *scope, PreParserFactory *factory)
Definition: preparser.h:1312
static void TearDownFunctionState(FunctionState *function_state)
Definition: preparser.h:1151
int DeclareArrowParametersFromExpression(PreParserExpression expression, PreParserScope *scope, Scanner::Location *dupe_loc, bool *ok)
Definition: preparser.h:1371
static bool IsEvalOrArguments(PreParserIdentifier identifier)
Definition: preparser.h:1154
static bool IsFutureStrictReserved(PreParserIdentifier identifier)
Definition: preparser.h:1179
PreParserExpression NewThrowReferenceError(const char *type, int pos)
Definition: preparser.h:1241
Expression ParseObjectLiteral(bool *ok)
Statement ParseReturnStatement(bool *ok)
Definition: preparser.cc:575
Statement ParseTryStatement(bool *ok)
Definition: preparser.cc:760
Statement ParseContinueStatement(bool *ok)
Definition: preparser.cc:539
void ParseLazyFunctionLiteralBody(bool *ok)
Definition: preparser.cc:927
Statement ParseVariableStatement(VariableDeclarationContext var_context, bool *ok)
Definition: preparser.cc:391
PreParseResult PreParseLazyFunction(StrictMode strict_mode, bool is_generator, ParserRecorder *log)
Definition: preparser.cc:121
Statement ParseFunctionDeclaration(bool *ok)
Definition: preparser.cc:338
Statement ParseWithStatement(bool *ok)
Definition: preparser.cc:601
PreParserStatementList ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, Variable *fvar, Token::Value fvar_init_op, bool is_generator, bool *ok)
Definition: preparser.h:1532
Statement ParseStatement(bool *ok)
Definition: preparser.cc:234
Statement ParseWhileStatement(bool *ok)
Definition: preparser.cc:668
PreParserStatement Statement
Definition: preparser.h:1413
Expression ParseV8Intrinsic(bool *ok)
Definition: preparser.cc:942
Statement ParseSourceElement(bool *ok)
Definition: preparser.cc:172
bool CheckInOrOf(bool accept_OF)
Definition: preparser.cc:681
Statement ParseSwitchStatement(bool *ok)
Definition: preparser.cc:621
Statement ParseForStatement(bool *ok)
Definition: preparser.cc:690
PreParserIdentifier Identifier
Definition: preparser.h:1411
Statement ParseClassDeclaration(bool *ok)
Definition: preparser.cc:359
Statement ParseExpressionOrLabelledStatement(bool *ok)
Definition: preparser.cc:493
Statement ParseVariableDeclarations(VariableDeclarationContext var_context, VariableDeclarationProperties *decl_props, int *num_decl, bool *ok)
Definition: preparser.cc:411
SourceElements ParseSourceElements(int end_token, bool *ok)
Definition: preparser.cc:203
Statement ParseDoWhileStatement(bool *ok)
Definition: preparser.cc:653
Expression ParseFunctionLiteral(Identifier name, Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, FunctionLiteral::FunctionType function_type, FunctionLiteral::ArityRestriction arity_restriction, bool *ok)
Definition: preparser.cc:823
Statement ParseThrowStatement(bool *ok)
Definition: preparser.cc:744
PreParser(Scanner *scanner, ParserRecorder *log, uintptr_t stack_limit)
Definition: preparser.h:1420
void SkipLazyFunctionBody(PreParserIdentifier function_name, int *materialized_literal_count, int *expected_property_count, bool *ok)
Statement ParseBlock(bool *ok)
Definition: preparser.cc:371
PreParserExpression Expression
Definition: preparser.h:1412
Expression ParseConditionalExpression(bool accept_IN, bool *ok)
Statement ParseDebuggerStatement(bool *ok)
Definition: preparser.cc:802
Statement ParseIfStatement(bool *ok)
Definition: preparser.cc:522
PreParseResult PreParseProgram()
Definition: preparser.h:1428
Statement ParseBreakStatement(bool *ok)
Definition: preparser.cc:557
static const int kNoPosition
Definition: assembler.h:317
Token::Value Next()
Definition: scanner.cc:219
Token::Value peek() const
Definition: scanner.h:361
int FindNumber(DuplicateFinder *finder, int value)
Definition: scanner.cc:1220
void SetHarmonyClasses(bool classes)
Definition: scanner.h:444
void SetHarmonyModules(bool modules)
Definition: scanner.h:432
bool HarmonyClasses() const
Definition: scanner.h:441
void SetHarmonyNumericLiterals(bool numeric_literals)
Definition: scanner.h:438
bool HarmonyModules() const
Definition: scanner.h:429
int FindSymbol(DuplicateFinder *finder, int value)
Definition: scanner.cc:1225
void SetHarmonyScoping(bool scoping)
Definition: scanner.h:426
Location peek_location() const
Definition: scanner.h:363
bool HarmonyNumericLiterals() const
Definition: scanner.h:435
bool HarmonyScoping() const
Definition: scanner.h:423
void clear_octal_position()
Definition: scanner.h:415
Location octal_position() const
Definition: scanner.h:414
Location location() const
Definition: scanner.h:356
static bool IsKeyword(Value tok)
Definition: token.h:186
static bool IsCompareOp(Value op)
Definition: token.h:202
static const char * String(Value tok)
Definition: token.h:276
static int Precedence(Value tok)
Definition: token.h:283
static bool IsUnaryOp(Value op)
Definition: token.h:261
static bool IsCountOp(Value op)
Definition: token.h:265
static bool IsAssignmentOp(Value tok)
Definition: token.h:190
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
#define COMMA
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
void USE(T)
Definition: macros.h:322
kFeedbackVectorOffset kHiddenPrototypeBit kReadOnlyPrototypeBit kDoNotCacheBit kIsTopLevelBit kAllowLazyCompilationWithoutContext has_duplicate_parameters
Definition: objects-inl.h:5448
kExpectedNofPropertiesOffset function_token_position
Definition: objects-inl.h:5513
DISABLE_ASAN uintptr_t GetCurrentStackPosition()
Definition: utils.h:1460
@ FUNCTION_SCOPE
Definition: globals.h:647
@ GLOBAL_SCOPE
Definition: globals.h:649
@ kNormalFunction
Definition: globals.h:776
@ kGeneratorFunction
Definition: globals.h:778
@ kConciseGeneratorMethod
Definition: globals.h:780
@ kConciseMethod
Definition: globals.h:779
@ kArrowFunction
Definition: globals.h:777
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define IN
#define CHECK_OK_CUSTOM(x)
Definition: preparser.h:1742
#define CHECK_OK
Definition: preparser.h:1735
@ STRING
PreParserExpression ObjectLiteralProperty
Definition: preparser.h:1132
PreParserExpression Expression
Definition: preparser.h:1128
Vector< PreParserIdentifier > ParameterIdentifierVector
Definition: preparser.h:1124
PreParserStatementList StatementList
Definition: preparser.h:1136
PreParserExpression ClassLiteral
Definition: preparser.h:1131
PreParserExpression YieldExpression
Definition: preparser.h:1129
PreParserExpressionList PropertyList
Definition: preparser.h:1135
PreParserExpression FunctionLiteral
Definition: preparser.h:1130
PreParserIdentifier Identifier
Definition: preparser.h:1127
PreParserExpressionList ExpressionList
Definition: preparser.h:1134
static Location invalid()
Definition: scanner.h:337
#define V8_INLINE
Definition: v8config.h:306