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