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/func-name-inferrer.h"
9 #include "src/hashmap.h"
10 #include "src/scopes.h"
11 #include "src/token.h"
12 #include "src/scanner.h"
13 #include "src/v8.h"
14
15 namespace v8 {
16 namespace internal {
17
18 // Common base class shared between parser and pre-parser. Traits encapsulate
19 // the differences between Parser and PreParser:
20
21 // - Return types: For example, Parser functions return Expression* and
22 // PreParser functions return PreParserExpression.
23
24 // - Creating parse tree nodes: Parser generates an AST during the recursive
25 // descent. PreParser doesn't create a tree. Instead, it passes around minimal
26 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain
27 // just enough data for the upper layer functions. PreParserFactory is
28 // responsible for creating these dummy objects. It provides a similar kind of
29 // interface as AstNodeFactory, so ParserBase doesn't need to care which one is
30 // used.
31
32 // - Miscellanous other tasks interleaved with the recursive descent. For
33 // example, Parser keeps track of which function literals should be marked as
34 // pretenured, and PreParser doesn't care.
35
36 // The traits are expected to contain the following typedefs:
37 // struct Traits {
38 // // In particular...
39 // struct Type {
40 // // Used by FunctionState and BlockState.
41 // typedef Scope;
42 // typedef GeneratorVariable;
43 // typedef Zone;
44 // // Return types for traversing functions.
45 // typedef Identifier;
46 // typedef Expression;
47 // typedef FunctionLiteral;
48 // typedef ObjectLiteralProperty;
49 // typedef Literal;
50 // typedef ExpressionList;
51 // typedef PropertyList;
52 // // For constructing objects returned by the traversing functions.
53 // typedef Factory;
54 // };
55 // // ...
56 // };
57
58 template <typename Traits>
59 class ParserBase : public Traits {
60 public:
61 // Shorten type names defined by Traits.
62 typedef typename Traits::Type::Expression ExpressionT;
63 typedef typename Traits::Type::Identifier IdentifierT;
64
ParserBase(Scanner * scanner,uintptr_t stack_limit,v8::Extension * extension,ParserRecorder * log,typename Traits::Type::Zone * zone,typename Traits::Type::Parser this_object)65 ParserBase(Scanner* scanner, uintptr_t stack_limit,
66 v8::Extension* extension,
67 ParserRecorder* log,
68 typename Traits::Type::Zone* zone,
69 typename Traits::Type::Parser this_object)
70 : Traits(this_object),
71 parenthesized_function_(false),
72 scope_(NULL),
73 function_state_(NULL),
74 extension_(extension),
75 fni_(NULL),
76 log_(log),
77 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
78 scanner_(scanner),
79 stack_limit_(stack_limit),
80 stack_overflow_(false),
81 allow_lazy_(false),
82 allow_natives_syntax_(false),
83 allow_generators_(false),
84 allow_for_of_(false),
85 zone_(zone) { }
86
87 // Getters that indicate whether certain syntactical constructs are
88 // allowed to be parsed by this instance of the parser.
allow_lazy()89 bool allow_lazy() const { return allow_lazy_; }
allow_natives_syntax()90 bool allow_natives_syntax() const { return allow_natives_syntax_; }
allow_generators()91 bool allow_generators() const { return allow_generators_; }
allow_for_of()92 bool allow_for_of() const { return allow_for_of_; }
allow_modules()93 bool allow_modules() const { return scanner()->HarmonyModules(); }
allow_harmony_scoping()94 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
allow_harmony_numeric_literals()95 bool allow_harmony_numeric_literals() const {
96 return scanner()->HarmonyNumericLiterals();
97 }
98
99 // Setters that determine whether certain syntactical constructs are
100 // allowed to be parsed by this instance of the parser.
set_allow_lazy(bool allow)101 void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
set_allow_natives_syntax(bool allow)102 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
set_allow_generators(bool allow)103 void set_allow_generators(bool allow) { allow_generators_ = allow; }
set_allow_for_of(bool allow)104 void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
set_allow_modules(bool allow)105 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
set_allow_harmony_scoping(bool allow)106 void set_allow_harmony_scoping(bool allow) {
107 scanner()->SetHarmonyScoping(allow);
108 }
set_allow_harmony_numeric_literals(bool allow)109 void set_allow_harmony_numeric_literals(bool allow) {
110 scanner()->SetHarmonyNumericLiterals(allow);
111 }
112
113 protected:
114 enum AllowEvalOrArgumentsAsIdentifier {
115 kAllowEvalOrArguments,
116 kDontAllowEvalOrArguments
117 };
118
119 enum Mode {
120 PARSE_LAZILY,
121 PARSE_EAGERLY
122 };
123
124 // ---------------------------------------------------------------------------
125 // FunctionState and BlockState together implement the parser's scope stack.
126 // The parser's current scope is in scope_. BlockState and FunctionState
127 // constructors push on the scope stack and the destructors pop. They are also
128 // used to hold the parser's per-function and per-block state.
129 class BlockState BASE_EMBEDDED {
130 public:
BlockState(typename Traits::Type::Scope ** scope_stack,typename Traits::Type::Scope * scope)131 BlockState(typename Traits::Type::Scope** scope_stack,
132 typename Traits::Type::Scope* scope)
133 : scope_stack_(scope_stack),
134 outer_scope_(*scope_stack),
135 scope_(scope) {
136 *scope_stack_ = scope_;
137 }
~BlockState()138 ~BlockState() { *scope_stack_ = outer_scope_; }
139
140 private:
141 typename Traits::Type::Scope** scope_stack_;
142 typename Traits::Type::Scope* outer_scope_;
143 typename Traits::Type::Scope* scope_;
144 };
145
146 class FunctionState BASE_EMBEDDED {
147 public:
148 FunctionState(
149 FunctionState** function_state_stack,
150 typename Traits::Type::Scope** scope_stack,
151 typename Traits::Type::Scope* scope,
152 typename Traits::Type::Zone* zone = NULL);
153 ~FunctionState();
154
NextMaterializedLiteralIndex()155 int NextMaterializedLiteralIndex() {
156 return next_materialized_literal_index_++;
157 }
materialized_literal_count()158 int materialized_literal_count() {
159 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
160 }
161
NextHandlerIndex()162 int NextHandlerIndex() { return next_handler_index_++; }
handler_count()163 int handler_count() { return next_handler_index_; }
164
AddProperty()165 void AddProperty() { expected_property_count_++; }
expected_property_count()166 int expected_property_count() { return expected_property_count_; }
167
set_is_generator(bool is_generator)168 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
is_generator()169 bool is_generator() const { return is_generator_; }
170
set_generator_object_variable(typename Traits::Type::GeneratorVariable * variable)171 void set_generator_object_variable(
172 typename Traits::Type::GeneratorVariable* variable) {
173 ASSERT(variable != NULL);
174 ASSERT(!is_generator());
175 generator_object_variable_ = variable;
176 is_generator_ = true;
177 }
generator_object_variable()178 typename Traits::Type::GeneratorVariable* generator_object_variable()
179 const {
180 return generator_object_variable_;
181 }
182
factory()183 typename Traits::Type::Factory* factory() { return &factory_; }
184
185 private:
186 // Used to assign an index to each literal that needs materialization in
187 // the function. Includes regexp literals, and boilerplate for object and
188 // array literals.
189 int next_materialized_literal_index_;
190
191 // Used to assign a per-function index to try and catch handlers.
192 int next_handler_index_;
193
194 // Properties count estimation.
195 int expected_property_count_;
196
197 // Whether the function is a generator.
198 bool is_generator_;
199 // For generators, this variable may hold the generator object. It variable
200 // is used by yield expressions and return statements. It is not necessary
201 // for generator functions to have this variable set.
202 Variable* generator_object_variable_;
203
204 FunctionState** function_state_stack_;
205 FunctionState* outer_function_state_;
206 typename Traits::Type::Scope** scope_stack_;
207 typename Traits::Type::Scope* outer_scope_;
208 int saved_ast_node_id_; // Only used by ParserTraits.
209 typename Traits::Type::Zone* extra_param_;
210 typename Traits::Type::Factory factory_;
211
212 friend class ParserTraits;
213 };
214
215 class ParsingModeScope BASE_EMBEDDED {
216 public:
ParsingModeScope(ParserBase * parser,Mode mode)217 ParsingModeScope(ParserBase* parser, Mode mode)
218 : parser_(parser),
219 old_mode_(parser->mode()) {
220 parser_->mode_ = mode;
221 }
~ParsingModeScope()222 ~ParsingModeScope() {
223 parser_->mode_ = old_mode_;
224 }
225
226 private:
227 ParserBase* parser_;
228 Mode old_mode_;
229 };
230
scanner()231 Scanner* scanner() const { return scanner_; }
position()232 int position() { return scanner_->location().beg_pos; }
peek_position()233 int peek_position() { return scanner_->peek_location().beg_pos; }
stack_overflow()234 bool stack_overflow() const { return stack_overflow_; }
set_stack_overflow()235 void set_stack_overflow() { stack_overflow_ = true; }
mode()236 Mode mode() const { return mode_; }
zone()237 typename Traits::Type::Zone* zone() const { return zone_; }
238
INLINE(Token::Value peek ())239 INLINE(Token::Value peek()) {
240 if (stack_overflow_) return Token::ILLEGAL;
241 return scanner()->peek();
242 }
243
INLINE(Token::Value Next ())244 INLINE(Token::Value Next()) {
245 if (stack_overflow_) return Token::ILLEGAL;
246 {
247 int marker;
248 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
249 // Any further calls to Next or peek will return the illegal token.
250 // The current call must return the next token, which might already
251 // have been peek'ed.
252 stack_overflow_ = true;
253 }
254 }
255 return scanner()->Next();
256 }
257
Consume(Token::Value token)258 void Consume(Token::Value token) {
259 Token::Value next = Next();
260 USE(next);
261 USE(token);
262 ASSERT(next == token);
263 }
264
Check(Token::Value token)265 bool Check(Token::Value token) {
266 Token::Value next = peek();
267 if (next == token) {
268 Consume(next);
269 return true;
270 }
271 return false;
272 }
273
Expect(Token::Value token,bool * ok)274 void Expect(Token::Value token, bool* ok) {
275 Token::Value next = Next();
276 if (next != token) {
277 ReportUnexpectedToken(next);
278 *ok = false;
279 }
280 }
281
ExpectSemicolon(bool * ok)282 void ExpectSemicolon(bool* ok) {
283 // Check for automatic semicolon insertion according to
284 // the rules given in ECMA-262, section 7.9, page 21.
285 Token::Value tok = peek();
286 if (tok == Token::SEMICOLON) {
287 Next();
288 return;
289 }
290 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
291 tok == Token::RBRACE ||
292 tok == Token::EOS) {
293 return;
294 }
295 Expect(Token::SEMICOLON, ok);
296 }
297
peek_any_identifier()298 bool peek_any_identifier() {
299 Token::Value next = peek();
300 return next == Token::IDENTIFIER ||
301 next == Token::FUTURE_RESERVED_WORD ||
302 next == Token::FUTURE_STRICT_RESERVED_WORD ||
303 next == Token::YIELD;
304 }
305
CheckContextualKeyword(Vector<const char> keyword)306 bool CheckContextualKeyword(Vector<const char> keyword) {
307 if (peek() == Token::IDENTIFIER &&
308 scanner()->is_next_contextual_keyword(keyword)) {
309 Consume(Token::IDENTIFIER);
310 return true;
311 }
312 return false;
313 }
314
ExpectContextualKeyword(Vector<const char> keyword,bool * ok)315 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
316 Expect(Token::IDENTIFIER, ok);
317 if (!*ok) return;
318 if (!scanner()->is_literal_contextual_keyword(keyword)) {
319 ReportUnexpectedToken(scanner()->current_token());
320 *ok = false;
321 }
322 }
323
324 // Checks whether an octal literal was last seen between beg_pos and end_pos.
325 // If so, reports an error. Only called for strict mode.
CheckOctalLiteral(int beg_pos,int end_pos,bool * ok)326 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
327 Scanner::Location octal = scanner()->octal_position();
328 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
329 octal.end_pos <= end_pos) {
330 ReportMessageAt(octal, "strict_octal_literal");
331 scanner()->clear_octal_position();
332 *ok = false;
333 }
334 }
335
336 // Determine precedence of given token.
Precedence(Token::Value token,bool accept_IN)337 static int Precedence(Token::Value token, bool accept_IN) {
338 if (token == Token::IN && !accept_IN)
339 return 0; // 0 precedence will terminate binary expression parsing
340 return Token::Precedence(token);
341 }
342
factory()343 typename Traits::Type::Factory* factory() {
344 return function_state_->factory();
345 }
346
strict_mode()347 StrictMode strict_mode() { return scope_->strict_mode(); }
is_generator()348 bool is_generator() const { return function_state_->is_generator(); }
349
350 // Report syntax errors.
351 void ReportMessage(const char* message, const char* arg = NULL,
352 bool is_reference_error = false) {
353 Scanner::Location source_location = scanner()->location();
354 Traits::ReportMessageAt(source_location, message, arg, is_reference_error);
355 }
356
357 void ReportMessageAt(Scanner::Location location, const char* message,
358 bool is_reference_error = false) {
359 Traits::ReportMessageAt(location, message, NULL, is_reference_error);
360 }
361
362 void ReportUnexpectedToken(Token::Value token);
363
364 // Recursive descent functions:
365
366 // Parses an identifier that is valid for the current scope, in particular it
367 // fails on strict mode future reserved keywords in a strict scope. If
368 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
369 // "arguments" as identifier even in strict mode (this is needed in cases like
370 // "var foo = eval;").
371 IdentifierT ParseIdentifier(
372 AllowEvalOrArgumentsAsIdentifier,
373 bool* ok);
374 // Parses an identifier or a strict mode future reserved word, and indicate
375 // whether it is strict mode future reserved.
376 IdentifierT ParseIdentifierOrStrictReservedWord(
377 bool* is_strict_reserved,
378 bool* ok);
379 IdentifierT ParseIdentifierName(bool* ok);
380 // Parses an identifier and determines whether or not it is 'get' or 'set'.
381 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get,
382 bool* is_set,
383 bool* ok);
384
385 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok);
386
387 ExpressionT ParsePrimaryExpression(bool* ok);
388 ExpressionT ParseExpression(bool accept_IN, bool* ok);
389 ExpressionT ParseArrayLiteral(bool* ok);
390 ExpressionT ParseObjectLiteral(bool* ok);
391 typename Traits::Type::ExpressionList ParseArguments(bool* ok);
392 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
393 ExpressionT ParseYieldExpression(bool* ok);
394 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
395 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
396 ExpressionT ParseUnaryExpression(bool* ok);
397 ExpressionT ParsePostfixExpression(bool* ok);
398 ExpressionT ParseLeftHandSideExpression(bool* ok);
399 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
400 ExpressionT ParseMemberExpression(bool* ok);
401 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
402 bool* ok);
403
404 // Checks if the expression is a valid reference expression (e.g., on the
405 // left-hand side of assignments). Although ruled out by ECMA as early errors,
406 // we allow calls for web compatibility and rewrite them to a runtime throw.
407 ExpressionT CheckAndRewriteReferenceExpression(
408 ExpressionT expression,
409 Scanner::Location location, const char* message, bool* ok);
410
411 // Used to detect duplicates in object literals. Each of the values
412 // kGetterProperty, kSetterProperty and kValueProperty represents
413 // a type of object literal property. When parsing a property, its
414 // type value is stored in the DuplicateFinder for the property name.
415 // Values are chosen so that having intersection bits means the there is
416 // an incompatibility.
417 // I.e., you can add a getter to a property that already has a setter, since
418 // kGetterProperty and kSetterProperty doesn't intersect, but not if it
419 // already has a getter or a value. Adding the getter to an existing
420 // setter will store the value (kGetterProperty | kSetterProperty), which
421 // is incompatible with adding any further properties.
422 enum PropertyKind {
423 kNone = 0,
424 // Bit patterns representing different object literal property types.
425 kGetterProperty = 1,
426 kSetterProperty = 2,
427 kValueProperty = 7,
428 // Helper constants.
429 kValueFlag = 4
430 };
431
432 // Validation per ECMA 262 - 11.1.5 "Object Initialiser".
433 class ObjectLiteralChecker {
434 public:
ObjectLiteralChecker(ParserBase * parser,StrictMode strict_mode)435 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode)
436 : parser_(parser),
437 finder_(scanner()->unicode_cache()),
438 strict_mode_(strict_mode) { }
439
440 void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
441
442 private:
parser()443 ParserBase* parser() const { return parser_; }
scanner()444 Scanner* scanner() const { return parser_->scanner(); }
445
446 // Checks the type of conflict based on values coming from PropertyType.
HasConflict(PropertyKind type1,PropertyKind type2)447 bool HasConflict(PropertyKind type1, PropertyKind type2) {
448 return (type1 & type2) != 0;
449 }
IsDataDataConflict(PropertyKind type1,PropertyKind type2)450 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
451 return ((type1 & type2) & kValueFlag) != 0;
452 }
IsDataAccessorConflict(PropertyKind type1,PropertyKind type2)453 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
454 return ((type1 ^ type2) & kValueFlag) != 0;
455 }
IsAccessorAccessorConflict(PropertyKind type1,PropertyKind type2)456 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
457 return ((type1 | type2) & kValueFlag) == 0;
458 }
459
460 ParserBase* parser_;
461 DuplicateFinder finder_;
462 StrictMode strict_mode_;
463 };
464
465 // If true, the next (and immediately following) function literal is
466 // preceded by a parenthesis.
467 // Heuristically that means that the function will be called immediately,
468 // so never lazily compile it.
469 bool parenthesized_function_;
470
471 typename Traits::Type::Scope* scope_; // Scope stack.
472 FunctionState* function_state_; // Function state stack.
473 v8::Extension* extension_;
474 FuncNameInferrer* fni_;
475 ParserRecorder* log_;
476 Mode mode_;
477
478 private:
479 Scanner* scanner_;
480 uintptr_t stack_limit_;
481 bool stack_overflow_;
482
483 bool allow_lazy_;
484 bool allow_natives_syntax_;
485 bool allow_generators_;
486 bool allow_for_of_;
487
488 typename Traits::Type::Zone* zone_; // Only used by Parser.
489 };
490
491
492 class PreParserIdentifier {
493 public:
PreParserIdentifier()494 PreParserIdentifier() : type_(kUnknownIdentifier) {}
Default()495 static PreParserIdentifier Default() {
496 return PreParserIdentifier(kUnknownIdentifier);
497 }
Eval()498 static PreParserIdentifier Eval() {
499 return PreParserIdentifier(kEvalIdentifier);
500 }
Arguments()501 static PreParserIdentifier Arguments() {
502 return PreParserIdentifier(kArgumentsIdentifier);
503 }
FutureReserved()504 static PreParserIdentifier FutureReserved() {
505 return PreParserIdentifier(kFutureReservedIdentifier);
506 }
FutureStrictReserved()507 static PreParserIdentifier FutureStrictReserved() {
508 return PreParserIdentifier(kFutureStrictReservedIdentifier);
509 }
Yield()510 static PreParserIdentifier Yield() {
511 return PreParserIdentifier(kYieldIdentifier);
512 }
IsEval()513 bool IsEval() { return type_ == kEvalIdentifier; }
IsArguments()514 bool IsArguments() { return type_ == kArgumentsIdentifier; }
IsEvalOrArguments()515 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
IsYield()516 bool IsYield() { return type_ == kYieldIdentifier; }
IsFutureReserved()517 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
IsFutureStrictReserved()518 bool IsFutureStrictReserved() {
519 return type_ == kFutureStrictReservedIdentifier;
520 }
IsValidStrictVariable()521 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
522
523 private:
524 enum Type {
525 kUnknownIdentifier,
526 kFutureReservedIdentifier,
527 kFutureStrictReservedIdentifier,
528 kYieldIdentifier,
529 kEvalIdentifier,
530 kArgumentsIdentifier
531 };
PreParserIdentifier(Type type)532 explicit PreParserIdentifier(Type type) : type_(type) {}
533 Type type_;
534
535 friend class PreParserExpression;
536 };
537
538
539 // Bits 0 and 1 are used to identify the type of expression:
540 // If bit 0 is set, it's an identifier.
541 // if bit 1 is set, it's a string literal.
542 // If neither is set, it's no particular type, and both set isn't
543 // use yet.
544 class PreParserExpression {
545 public:
Default()546 static PreParserExpression Default() {
547 return PreParserExpression(kUnknownExpression);
548 }
549
FromIdentifier(PreParserIdentifier id)550 static PreParserExpression FromIdentifier(PreParserIdentifier id) {
551 return PreParserExpression(kIdentifierFlag |
552 (id.type_ << kIdentifierShift));
553 }
554
StringLiteral()555 static PreParserExpression StringLiteral() {
556 return PreParserExpression(kUnknownStringLiteral);
557 }
558
UseStrictStringLiteral()559 static PreParserExpression UseStrictStringLiteral() {
560 return PreParserExpression(kUseStrictString);
561 }
562
This()563 static PreParserExpression This() {
564 return PreParserExpression(kThisExpression);
565 }
566
ThisProperty()567 static PreParserExpression ThisProperty() {
568 return PreParserExpression(kThisPropertyExpression);
569 }
570
Property()571 static PreParserExpression Property() {
572 return PreParserExpression(kPropertyExpression);
573 }
574
Call()575 static PreParserExpression Call() {
576 return PreParserExpression(kCallExpression);
577 }
578
IsIdentifier()579 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
580
AsIdentifier()581 PreParserIdentifier AsIdentifier() {
582 ASSERT(IsIdentifier());
583 return PreParserIdentifier(
584 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
585 }
586
IsStringLiteral()587 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
588
IsUseStrictLiteral()589 bool IsUseStrictLiteral() {
590 return (code_ & kStringLiteralMask) == kUseStrictString;
591 }
592
IsThis()593 bool IsThis() { return code_ == kThisExpression; }
594
IsThisProperty()595 bool IsThisProperty() { return code_ == kThisPropertyExpression; }
596
IsProperty()597 bool IsProperty() {
598 return code_ == kPropertyExpression || code_ == kThisPropertyExpression;
599 }
600
IsCall()601 bool IsCall() { return code_ == kCallExpression; }
602
IsValidReferenceExpression()603 bool IsValidReferenceExpression() {
604 return IsIdentifier() || IsProperty();
605 }
606
607 // At the moment PreParser doesn't track these expression types.
IsFunctionLiteral()608 bool IsFunctionLiteral() const { return false; }
IsCallNew()609 bool IsCallNew() const { return false; }
610
AsFunctionLiteral()611 PreParserExpression AsFunctionLiteral() { return *this; }
612
613 // Dummy implementation for making expression->somefunc() work in both Parser
614 // and PreParser.
615 PreParserExpression* operator->() { return this; }
616
617 // More dummy implementations of things PreParser doesn't need to track:
set_index(int index)618 void set_index(int index) {} // For YieldExpressions
set_parenthesized()619 void set_parenthesized() {}
620
621 private:
622 // Least significant 2 bits are used as flags. Bits 0 and 1 represent
623 // identifiers or strings literals, and are mutually exclusive, but can both
624 // be absent. If the expression is an identifier or a string literal, the
625 // other bits describe the type (see PreParserIdentifier::Type and string
626 // literal constants below).
627 enum {
628 kUnknownExpression = 0,
629 // Identifiers
630 kIdentifierFlag = 1, // Used to detect labels.
631 kIdentifierShift = 3,
632
633 kStringLiteralFlag = 2, // Used to detect directive prologue.
634 kUnknownStringLiteral = kStringLiteralFlag,
635 kUseStrictString = kStringLiteralFlag | 8,
636 kStringLiteralMask = kUseStrictString,
637
638 // Below here applies if neither identifier nor string literal. Reserve the
639 // 2 least significant bits for flags.
640 kThisExpression = 1 << 2,
641 kThisPropertyExpression = 2 << 2,
642 kPropertyExpression = 3 << 2,
643 kCallExpression = 4 << 2
644 };
645
PreParserExpression(int expression_code)646 explicit PreParserExpression(int expression_code) : code_(expression_code) {}
647
648 int code_;
649 };
650
651
652 // PreParserExpressionList doesn't actually store the expressions because
653 // PreParser doesn't need to.
654 class PreParserExpressionList {
655 public:
656 // These functions make list->Add(some_expression) work (and do nothing).
PreParserExpressionList()657 PreParserExpressionList() : length_(0) {}
658 PreParserExpressionList* operator->() { return this; }
Add(PreParserExpression,void *)659 void Add(PreParserExpression, void*) { ++length_; }
length()660 int length() const { return length_; }
661 private:
662 int length_;
663 };
664
665
666 class PreParserStatement {
667 public:
Default()668 static PreParserStatement Default() {
669 return PreParserStatement(kUnknownStatement);
670 }
671
FunctionDeclaration()672 static PreParserStatement FunctionDeclaration() {
673 return PreParserStatement(kFunctionDeclaration);
674 }
675
676 // Creates expression statement from expression.
677 // Preserves being an unparenthesized string literal, possibly
678 // "use strict".
ExpressionStatement(PreParserExpression expression)679 static PreParserStatement ExpressionStatement(
680 PreParserExpression expression) {
681 if (expression.IsUseStrictLiteral()) {
682 return PreParserStatement(kUseStrictExpressionStatement);
683 }
684 if (expression.IsStringLiteral()) {
685 return PreParserStatement(kStringLiteralExpressionStatement);
686 }
687 return Default();
688 }
689
IsStringLiteral()690 bool IsStringLiteral() {
691 return code_ == kStringLiteralExpressionStatement;
692 }
693
IsUseStrictLiteral()694 bool IsUseStrictLiteral() {
695 return code_ == kUseStrictExpressionStatement;
696 }
697
IsFunctionDeclaration()698 bool IsFunctionDeclaration() {
699 return code_ == kFunctionDeclaration;
700 }
701
702 private:
703 enum Type {
704 kUnknownStatement,
705 kStringLiteralExpressionStatement,
706 kUseStrictExpressionStatement,
707 kFunctionDeclaration
708 };
709
PreParserStatement(Type code)710 explicit PreParserStatement(Type code) : code_(code) {}
711 Type code_;
712 };
713
714
715
716 // PreParserStatementList doesn't actually store the statements because
717 // the PreParser does not need them.
718 class PreParserStatementList {
719 public:
720 // These functions make list->Add(some_expression) work as no-ops.
PreParserStatementList()721 PreParserStatementList() {}
722 PreParserStatementList* operator->() { return this; }
Add(PreParserStatement,void *)723 void Add(PreParserStatement, void*) {}
724 };
725
726
727 class PreParserScope {
728 public:
PreParserScope(PreParserScope * outer_scope,ScopeType scope_type)729 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type)
730 : scope_type_(scope_type) {
731 strict_mode_ = outer_scope ? outer_scope->strict_mode() : SLOPPY;
732 }
733
type()734 ScopeType type() { return scope_type_; }
strict_mode()735 StrictMode strict_mode() const { return strict_mode_; }
SetStrictMode(StrictMode strict_mode)736 void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
737
738 private:
739 ScopeType scope_type_;
740 StrictMode strict_mode_;
741 };
742
743
744 class PreParserFactory {
745 public:
PreParserFactory(void * extra_param)746 explicit PreParserFactory(void* extra_param) {}
NewLiteral(PreParserIdentifier identifier,int pos)747 PreParserExpression NewLiteral(PreParserIdentifier identifier,
748 int pos) {
749 return PreParserExpression::Default();
750 }
NewNumberLiteral(double number,int pos)751 PreParserExpression NewNumberLiteral(double number,
752 int pos) {
753 return PreParserExpression::Default();
754 }
NewRegExpLiteral(PreParserIdentifier js_pattern,PreParserIdentifier js_flags,int literal_index,int pos)755 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
756 PreParserIdentifier js_flags,
757 int literal_index,
758 int pos) {
759 return PreParserExpression::Default();
760 }
NewArrayLiteral(PreParserExpressionList values,int literal_index,int pos)761 PreParserExpression NewArrayLiteral(PreParserExpressionList values,
762 int literal_index,
763 int pos) {
764 return PreParserExpression::Default();
765 }
NewObjectLiteralProperty(bool is_getter,PreParserExpression value,int pos)766 PreParserExpression NewObjectLiteralProperty(bool is_getter,
767 PreParserExpression value,
768 int pos) {
769 return PreParserExpression::Default();
770 }
NewObjectLiteralProperty(PreParserExpression key,PreParserExpression value)771 PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
772 PreParserExpression value) {
773 return PreParserExpression::Default();
774 }
NewObjectLiteral(PreParserExpressionList properties,int literal_index,int boilerplate_properties,bool has_function,int pos)775 PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
776 int literal_index,
777 int boilerplate_properties,
778 bool has_function,
779 int pos) {
780 return PreParserExpression::Default();
781 }
NewVariableProxy(void * generator_variable)782 PreParserExpression NewVariableProxy(void* generator_variable) {
783 return PreParserExpression::Default();
784 }
NewProperty(PreParserExpression obj,PreParserExpression key,int pos)785 PreParserExpression NewProperty(PreParserExpression obj,
786 PreParserExpression key,
787 int pos) {
788 if (obj.IsThis()) {
789 return PreParserExpression::ThisProperty();
790 }
791 return PreParserExpression::Property();
792 }
NewUnaryOperation(Token::Value op,PreParserExpression expression,int pos)793 PreParserExpression NewUnaryOperation(Token::Value op,
794 PreParserExpression expression,
795 int pos) {
796 return PreParserExpression::Default();
797 }
NewBinaryOperation(Token::Value op,PreParserExpression left,PreParserExpression right,int pos)798 PreParserExpression NewBinaryOperation(Token::Value op,
799 PreParserExpression left,
800 PreParserExpression right, int pos) {
801 return PreParserExpression::Default();
802 }
NewCompareOperation(Token::Value op,PreParserExpression left,PreParserExpression right,int pos)803 PreParserExpression NewCompareOperation(Token::Value op,
804 PreParserExpression left,
805 PreParserExpression right, int pos) {
806 return PreParserExpression::Default();
807 }
NewAssignment(Token::Value op,PreParserExpression left,PreParserExpression right,int pos)808 PreParserExpression NewAssignment(Token::Value op,
809 PreParserExpression left,
810 PreParserExpression right,
811 int pos) {
812 return PreParserExpression::Default();
813 }
NewYield(PreParserExpression generator_object,PreParserExpression expression,Yield::Kind yield_kind,int pos)814 PreParserExpression NewYield(PreParserExpression generator_object,
815 PreParserExpression expression,
816 Yield::Kind yield_kind,
817 int pos) {
818 return PreParserExpression::Default();
819 }
NewConditional(PreParserExpression condition,PreParserExpression then_expression,PreParserExpression else_expression,int pos)820 PreParserExpression NewConditional(PreParserExpression condition,
821 PreParserExpression then_expression,
822 PreParserExpression else_expression,
823 int pos) {
824 return PreParserExpression::Default();
825 }
NewCountOperation(Token::Value op,bool is_prefix,PreParserExpression expression,int pos)826 PreParserExpression NewCountOperation(Token::Value op,
827 bool is_prefix,
828 PreParserExpression expression,
829 int pos) {
830 return PreParserExpression::Default();
831 }
NewCall(PreParserExpression expression,PreParserExpressionList arguments,int pos)832 PreParserExpression NewCall(PreParserExpression expression,
833 PreParserExpressionList arguments,
834 int pos) {
835 return PreParserExpression::Call();
836 }
NewCallNew(PreParserExpression expression,PreParserExpressionList arguments,int pos)837 PreParserExpression NewCallNew(PreParserExpression expression,
838 PreParserExpressionList arguments,
839 int pos) {
840 return PreParserExpression::Default();
841 }
842 };
843
844
845 class PreParser;
846
847 class PreParserTraits {
848 public:
849 struct Type {
850 // TODO(marja): To be removed. The Traits object should contain all the data
851 // it needs.
852 typedef PreParser* Parser;
853
854 // Used by FunctionState and BlockState.
855 typedef PreParserScope Scope;
856 // PreParser doesn't need to store generator variables.
857 typedef void GeneratorVariable;
858 // No interaction with Zones.
859 typedef void Zone;
860
861 // Return types for traversing functions.
862 typedef PreParserIdentifier Identifier;
863 typedef PreParserExpression Expression;
864 typedef PreParserExpression YieldExpression;
865 typedef PreParserExpression FunctionLiteral;
866 typedef PreParserExpression ObjectLiteralProperty;
867 typedef PreParserExpression Literal;
868 typedef PreParserExpressionList ExpressionList;
869 typedef PreParserExpressionList PropertyList;
870 typedef PreParserStatementList StatementList;
871
872 // For constructing objects returned by the traversing functions.
873 typedef PreParserFactory Factory;
874 };
875
PreParserTraits(PreParser * pre_parser)876 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
877
878 // Custom operations executed when FunctionStates are created and
879 // destructed. (The PreParser doesn't need to do anything.)
880 template<typename FunctionState>
SetUpFunctionState(FunctionState * function_state,void *)881 static void SetUpFunctionState(FunctionState* function_state, void*) {}
882 template<typename FunctionState>
TearDownFunctionState(FunctionState * function_state,void *)883 static void TearDownFunctionState(FunctionState* function_state, void*) {}
884
885 // Helper functions for recursive descent.
IsEvalOrArguments(PreParserIdentifier identifier)886 static bool IsEvalOrArguments(PreParserIdentifier identifier) {
887 return identifier.IsEvalOrArguments();
888 }
889
890 // Returns true if the expression is of type "this.foo".
IsThisProperty(PreParserExpression expression)891 static bool IsThisProperty(PreParserExpression expression) {
892 return expression.IsThisProperty();
893 }
894
IsIdentifier(PreParserExpression expression)895 static bool IsIdentifier(PreParserExpression expression) {
896 return expression.IsIdentifier();
897 }
898
AsIdentifier(PreParserExpression expression)899 static PreParserIdentifier AsIdentifier(PreParserExpression expression) {
900 return expression.AsIdentifier();
901 }
902
IsBoilerplateProperty(PreParserExpression property)903 static bool IsBoilerplateProperty(PreParserExpression property) {
904 // PreParser doesn't count boilerplate properties.
905 return false;
906 }
907
IsArrayIndex(PreParserIdentifier string,uint32_t * index)908 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
909 return false;
910 }
911
912 // Functions for encapsulating the differences between parsing and preparsing;
913 // operations interleaved with the recursive descent.
PushLiteralName(FuncNameInferrer * fni,PreParserIdentifier id)914 static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
915 // PreParser should not use FuncNameInferrer.
916 UNREACHABLE();
917 }
PushPropertyName(FuncNameInferrer * fni,PreParserExpression expression)918 static void PushPropertyName(FuncNameInferrer* fni,
919 PreParserExpression expression) {
920 // PreParser should not use FuncNameInferrer.
921 UNREACHABLE();
922 }
923
CheckFunctionLiteralInsideTopLevelObjectLiteral(PreParserScope * scope,PreParserExpression value,bool * has_function)924 static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
925 PreParserScope* scope, PreParserExpression value, bool* has_function) {}
926
CheckAssigningFunctionLiteralToProperty(PreParserExpression left,PreParserExpression right)927 static void CheckAssigningFunctionLiteralToProperty(
928 PreParserExpression left, PreParserExpression right) {}
929
930 // PreParser doesn't need to keep track of eval calls.
CheckPossibleEvalCall(PreParserExpression expression,PreParserScope * scope)931 static void CheckPossibleEvalCall(PreParserExpression expression,
932 PreParserScope* scope) {}
933
MarkExpressionAsLValue(PreParserExpression expression)934 static PreParserExpression MarkExpressionAsLValue(
935 PreParserExpression expression) {
936 // TODO(marja): To be able to produce the same errors, the preparser needs
937 // to start tracking which expressions are variables and which are lvalues.
938 return expression;
939 }
940
ShortcutNumericLiteralBinaryExpression(PreParserExpression * x,PreParserExpression y,Token::Value op,int pos,PreParserFactory * factory)941 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
942 PreParserExpression y,
943 Token::Value op,
944 int pos,
945 PreParserFactory* factory) {
946 return false;
947 }
948
BuildUnaryExpression(PreParserExpression expression,Token::Value op,int pos,PreParserFactory * factory)949 PreParserExpression BuildUnaryExpression(PreParserExpression expression,
950 Token::Value op, int pos,
951 PreParserFactory* factory) {
952 return PreParserExpression::Default();
953 }
954
NewThrowReferenceError(const char * type,int pos)955 PreParserExpression NewThrowReferenceError(const char* type, int pos) {
956 return PreParserExpression::Default();
957 }
NewThrowSyntaxError(const char * type,Handle<Object> arg,int pos)958 PreParserExpression NewThrowSyntaxError(
959 const char* type, Handle<Object> arg, int pos) {
960 return PreParserExpression::Default();
961 }
NewThrowTypeError(const char * type,Handle<Object> arg,int pos)962 PreParserExpression NewThrowTypeError(
963 const char* type, Handle<Object> arg, int pos) {
964 return PreParserExpression::Default();
965 }
966
967 // Reporting errors.
968 void ReportMessageAt(Scanner::Location location,
969 const char* message,
970 const char* arg = NULL,
971 bool is_reference_error = false);
972 void ReportMessageAt(int start_pos,
973 int end_pos,
974 const char* message,
975 const char* arg = NULL,
976 bool is_reference_error = false);
977
978 // "null" return type creators.
EmptyIdentifier()979 static PreParserIdentifier EmptyIdentifier() {
980 return PreParserIdentifier::Default();
981 }
EmptyExpression()982 static PreParserExpression EmptyExpression() {
983 return PreParserExpression::Default();
984 }
EmptyLiteral()985 static PreParserExpression EmptyLiteral() {
986 return PreParserExpression::Default();
987 }
NullExpressionList()988 static PreParserExpressionList NullExpressionList() {
989 return PreParserExpressionList();
990 }
991
992 // Odd-ball literal creators.
GetLiteralTheHole(int position,PreParserFactory * factory)993 static PreParserExpression GetLiteralTheHole(int position,
994 PreParserFactory* factory) {
995 return PreParserExpression::Default();
996 }
997
998 // Producing data during the recursive descent.
999 PreParserIdentifier GetSymbol(Scanner* scanner);
NextLiteralString(Scanner * scanner,PretenureFlag tenured)1000 static PreParserIdentifier NextLiteralString(Scanner* scanner,
1001 PretenureFlag tenured) {
1002 return PreParserIdentifier::Default();
1003 }
1004
ThisExpression(PreParserScope * scope,PreParserFactory * factory)1005 static PreParserExpression ThisExpression(PreParserScope* scope,
1006 PreParserFactory* factory) {
1007 return PreParserExpression::This();
1008 }
1009
ExpressionFromLiteral(Token::Value token,int pos,Scanner * scanner,PreParserFactory * factory)1010 static PreParserExpression ExpressionFromLiteral(
1011 Token::Value token, int pos, Scanner* scanner,
1012 PreParserFactory* factory) {
1013 return PreParserExpression::Default();
1014 }
1015
ExpressionFromIdentifier(PreParserIdentifier name,int pos,PreParserScope * scope,PreParserFactory * factory)1016 static PreParserExpression ExpressionFromIdentifier(
1017 PreParserIdentifier name, int pos, PreParserScope* scope,
1018 PreParserFactory* factory) {
1019 return PreParserExpression::FromIdentifier(name);
1020 }
1021
1022 PreParserExpression ExpressionFromString(int pos,
1023 Scanner* scanner,
1024 PreParserFactory* factory = NULL);
1025
NewExpressionList(int size,void * zone)1026 static PreParserExpressionList NewExpressionList(int size, void* zone) {
1027 return PreParserExpressionList();
1028 }
1029
NewStatementList(int size,void * zone)1030 static PreParserStatementList NewStatementList(int size, void* zone) {
1031 return PreParserStatementList();
1032 }
1033
NewPropertyList(int size,void * zone)1034 static PreParserExpressionList NewPropertyList(int size, void* zone) {
1035 return PreParserExpressionList();
1036 }
1037
1038 // Temporary glue; these functions will move to ParserBase.
1039 PreParserExpression ParseV8Intrinsic(bool* ok);
1040 PreParserExpression ParseFunctionLiteral(
1041 PreParserIdentifier name,
1042 Scanner::Location function_name_location,
1043 bool name_is_strict_reserved,
1044 bool is_generator,
1045 int function_token_position,
1046 FunctionLiteral::FunctionType type,
1047 FunctionLiteral::ArityRestriction arity_restriction,
1048 bool* ok);
1049
1050 private:
1051 PreParser* pre_parser_;
1052 };
1053
1054
1055 // Preparsing checks a JavaScript program and emits preparse-data that helps
1056 // a later parsing to be faster.
1057 // See preparse-data-format.h for the data format.
1058
1059 // The PreParser checks that the syntax follows the grammar for JavaScript,
1060 // and collects some information about the program along the way.
1061 // The grammar check is only performed in order to understand the program
1062 // sufficiently to deduce some information about it, that can be used
1063 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
1064 // rather it is to speed up properly written and correct programs.
1065 // That means that contextual checks (like a label being declared where
1066 // it is used) are generally omitted.
1067 class PreParser : public ParserBase<PreParserTraits> {
1068 public:
1069 typedef PreParserIdentifier Identifier;
1070 typedef PreParserExpression Expression;
1071 typedef PreParserStatement Statement;
1072
1073 enum PreParseResult {
1074 kPreParseStackOverflow,
1075 kPreParseSuccess
1076 };
1077
PreParser(Scanner * scanner,ParserRecorder * log,uintptr_t stack_limit)1078 PreParser(Scanner* scanner, ParserRecorder* log, uintptr_t stack_limit)
1079 : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, NULL,
1080 this) {}
1081
1082 // Pre-parse the program from the character stream; returns true on
1083 // success (even if parsing failed, the pre-parse data successfully
1084 // captured the syntax error), and false if a stack-overflow happened
1085 // during parsing.
PreParseProgram()1086 PreParseResult PreParseProgram() {
1087 PreParserScope scope(scope_, GLOBAL_SCOPE);
1088 FunctionState top_scope(&function_state_, &scope_, &scope, NULL);
1089 bool ok = true;
1090 int start_position = scanner()->peek_location().beg_pos;
1091 ParseSourceElements(Token::EOS, &ok);
1092 if (stack_overflow()) return kPreParseStackOverflow;
1093 if (!ok) {
1094 ReportUnexpectedToken(scanner()->current_token());
1095 } else if (scope_->strict_mode() == STRICT) {
1096 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
1097 }
1098 return kPreParseSuccess;
1099 }
1100
1101 // Parses a single function literal, from the opening parentheses before
1102 // parameters to the closing brace after the body.
1103 // Returns a FunctionEntry describing the body of the function in enough
1104 // detail that it can be lazily compiled.
1105 // The scanner is expected to have matched the "function" or "function*"
1106 // keyword and parameters, and have consumed the initial '{'.
1107 // At return, unless an error occurred, the scanner is positioned before the
1108 // the final '}'.
1109 PreParseResult PreParseLazyFunction(StrictMode strict_mode,
1110 bool is_generator,
1111 ParserRecorder* log);
1112
1113 private:
1114 friend class PreParserTraits;
1115
1116 // These types form an algebra over syntactic categories that is just
1117 // rich enough to let us recognize and propagate the constructs that
1118 // are either being counted in the preparser data, or is important
1119 // to throw the correct syntax error exceptions.
1120
1121 enum VariableDeclarationContext {
1122 kSourceElement,
1123 kStatement,
1124 kForStatement
1125 };
1126
1127 // If a list of variable declarations includes any initializers.
1128 enum VariableDeclarationProperties {
1129 kHasInitializers,
1130 kHasNoInitializers
1131 };
1132
1133
1134 enum SourceElements {
1135 kUnknownSourceElements
1136 };
1137
1138 // All ParseXXX functions take as the last argument an *ok parameter
1139 // which is set to false if parsing failed; it is unchanged otherwise.
1140 // By making the 'exception handling' explicit, we are forced to check
1141 // for failure at the call sites.
1142 Statement ParseSourceElement(bool* ok);
1143 SourceElements ParseSourceElements(int end_token, bool* ok);
1144 Statement ParseStatement(bool* ok);
1145 Statement ParseFunctionDeclaration(bool* ok);
1146 Statement ParseBlock(bool* ok);
1147 Statement ParseVariableStatement(VariableDeclarationContext var_context,
1148 bool* ok);
1149 Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
1150 VariableDeclarationProperties* decl_props,
1151 int* num_decl,
1152 bool* ok);
1153 Statement ParseExpressionOrLabelledStatement(bool* ok);
1154 Statement ParseIfStatement(bool* ok);
1155 Statement ParseContinueStatement(bool* ok);
1156 Statement ParseBreakStatement(bool* ok);
1157 Statement ParseReturnStatement(bool* ok);
1158 Statement ParseWithStatement(bool* ok);
1159 Statement ParseSwitchStatement(bool* ok);
1160 Statement ParseDoWhileStatement(bool* ok);
1161 Statement ParseWhileStatement(bool* ok);
1162 Statement ParseForStatement(bool* ok);
1163 Statement ParseThrowStatement(bool* ok);
1164 Statement ParseTryStatement(bool* ok);
1165 Statement ParseDebuggerStatement(bool* ok);
1166 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
1167 Expression ParseObjectLiteral(bool* ok);
1168 Expression ParseV8Intrinsic(bool* ok);
1169
1170 Expression ParseFunctionLiteral(
1171 Identifier name,
1172 Scanner::Location function_name_location,
1173 bool name_is_strict_reserved,
1174 bool is_generator,
1175 int function_token_pos,
1176 FunctionLiteral::FunctionType function_type,
1177 FunctionLiteral::ArityRestriction arity_restriction,
1178 bool* ok);
1179 void ParseLazyFunctionLiteralBody(bool* ok);
1180
1181 bool CheckInOrOf(bool accept_OF);
1182 };
1183
1184 template<class Traits>
FunctionState(FunctionState ** function_state_stack,typename Traits::Type::Scope ** scope_stack,typename Traits::Type::Scope * scope,typename Traits::Type::Zone * extra_param)1185 ParserBase<Traits>::FunctionState::FunctionState(
1186 FunctionState** function_state_stack,
1187 typename Traits::Type::Scope** scope_stack,
1188 typename Traits::Type::Scope* scope,
1189 typename Traits::Type::Zone* extra_param)
1190 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
1191 next_handler_index_(0),
1192 expected_property_count_(0),
1193 is_generator_(false),
1194 generator_object_variable_(NULL),
1195 function_state_stack_(function_state_stack),
1196 outer_function_state_(*function_state_stack),
1197 scope_stack_(scope_stack),
1198 outer_scope_(*scope_stack),
1199 saved_ast_node_id_(0),
1200 extra_param_(extra_param),
1201 factory_(extra_param) {
1202 *scope_stack_ = scope;
1203 *function_state_stack = this;
1204 Traits::SetUpFunctionState(this, extra_param);
1205 }
1206
1207
1208 template<class Traits>
~FunctionState()1209 ParserBase<Traits>::FunctionState::~FunctionState() {
1210 *scope_stack_ = outer_scope_;
1211 *function_state_stack_ = outer_function_state_;
1212 Traits::TearDownFunctionState(this, extra_param_);
1213 }
1214
1215
1216 template<class Traits>
ReportUnexpectedToken(Token::Value token)1217 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
1218 Scanner::Location source_location = scanner()->location();
1219
1220 // Four of the tokens are treated specially
1221 switch (token) {
1222 case Token::EOS:
1223 return ReportMessageAt(source_location, "unexpected_eos");
1224 case Token::NUMBER:
1225 return ReportMessageAt(source_location, "unexpected_token_number");
1226 case Token::STRING:
1227 return ReportMessageAt(source_location, "unexpected_token_string");
1228 case Token::IDENTIFIER:
1229 return ReportMessageAt(source_location, "unexpected_token_identifier");
1230 case Token::FUTURE_RESERVED_WORD:
1231 return ReportMessageAt(source_location, "unexpected_reserved");
1232 case Token::YIELD:
1233 case Token::FUTURE_STRICT_RESERVED_WORD:
1234 return ReportMessageAt(source_location, strict_mode() == SLOPPY
1235 ? "unexpected_token_identifier" : "unexpected_strict_reserved");
1236 default:
1237 const char* name = Token::String(token);
1238 ASSERT(name != NULL);
1239 Traits::ReportMessageAt(source_location, "unexpected_token", name);
1240 }
1241 }
1242
1243
1244 template<class Traits>
ParseIdentifier(AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,bool * ok)1245 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
1246 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
1247 bool* ok) {
1248 Token::Value next = Next();
1249 if (next == Token::IDENTIFIER) {
1250 IdentifierT name = this->GetSymbol(scanner());
1251 if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
1252 strict_mode() == STRICT && this->IsEvalOrArguments(name)) {
1253 ReportMessage("strict_eval_arguments");
1254 *ok = false;
1255 }
1256 return name;
1257 } else if (strict_mode() == SLOPPY &&
1258 (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1259 (next == Token::YIELD && !is_generator()))) {
1260 return this->GetSymbol(scanner());
1261 } else {
1262 this->ReportUnexpectedToken(next);
1263 *ok = false;
1264 return Traits::EmptyIdentifier();
1265 }
1266 }
1267
1268
1269 template <class Traits>
1270 typename ParserBase<Traits>::IdentifierT ParserBase<
ParseIdentifierOrStrictReservedWord(bool * is_strict_reserved,bool * ok)1271 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
1272 bool* ok) {
1273 Token::Value next = Next();
1274 if (next == Token::IDENTIFIER) {
1275 *is_strict_reserved = false;
1276 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1277 (next == Token::YIELD && !this->is_generator())) {
1278 *is_strict_reserved = true;
1279 } else {
1280 ReportUnexpectedToken(next);
1281 *ok = false;
1282 return Traits::EmptyIdentifier();
1283 }
1284 return this->GetSymbol(scanner());
1285 }
1286
1287
1288 template <class Traits>
1289 typename ParserBase<Traits>::IdentifierT
ParseIdentifierName(bool * ok)1290 ParserBase<Traits>::ParseIdentifierName(bool* ok) {
1291 Token::Value next = Next();
1292 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
1293 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
1294 this->ReportUnexpectedToken(next);
1295 *ok = false;
1296 return Traits::EmptyIdentifier();
1297 }
1298 return this->GetSymbol(scanner());
1299 }
1300
1301
1302 template <class Traits>
1303 typename ParserBase<Traits>::IdentifierT
ParseIdentifierNameOrGetOrSet(bool * is_get,bool * is_set,bool * ok)1304 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
1305 bool* is_set,
1306 bool* ok) {
1307 IdentifierT result = ParseIdentifierName(ok);
1308 if (!*ok) return Traits::EmptyIdentifier();
1309 scanner()->IsGetOrSet(is_get, is_set);
1310 return result;
1311 }
1312
1313
1314 template <class Traits>
ParseRegExpLiteral(bool seen_equal,bool * ok)1315 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
1316 bool seen_equal, bool* ok) {
1317 int pos = peek_position();
1318 if (!scanner()->ScanRegExpPattern(seen_equal)) {
1319 Next();
1320 ReportMessage("unterminated_regexp");
1321 *ok = false;
1322 return Traits::EmptyExpression();
1323 }
1324
1325 int literal_index = function_state_->NextMaterializedLiteralIndex();
1326
1327 IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED);
1328 if (!scanner()->ScanRegExpFlags()) {
1329 Next();
1330 ReportMessage("invalid_regexp_flags");
1331 *ok = false;
1332 return Traits::EmptyExpression();
1333 }
1334 IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED);
1335 Next();
1336 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
1337 }
1338
1339
1340 #define CHECK_OK ok); \
1341 if (!*ok) return this->EmptyExpression(); \
1342 ((void)0
1343 #define DUMMY ) // to make indentation work
1344 #undef DUMMY
1345
1346 // Used in functions where the return type is not ExpressionT.
1347 #define CHECK_OK_CUSTOM(x) ok); \
1348 if (!*ok) return this->x(); \
1349 ((void)0
1350 #define DUMMY ) // to make indentation work
1351 #undef DUMMY
1352
1353 template <class Traits>
1354 typename ParserBase<Traits>::ExpressionT
ParsePrimaryExpression(bool * ok)1355 ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
1356 // PrimaryExpression ::
1357 // 'this'
1358 // 'null'
1359 // 'true'
1360 // 'false'
1361 // Identifier
1362 // Number
1363 // String
1364 // ArrayLiteral
1365 // ObjectLiteral
1366 // RegExpLiteral
1367 // '(' Expression ')'
1368
1369 int pos = peek_position();
1370 ExpressionT result = this->EmptyExpression();
1371 Token::Value token = peek();
1372 switch (token) {
1373 case Token::THIS: {
1374 Consume(Token::THIS);
1375 result = this->ThisExpression(scope_, factory());
1376 break;
1377 }
1378
1379 case Token::NULL_LITERAL:
1380 case Token::TRUE_LITERAL:
1381 case Token::FALSE_LITERAL:
1382 case Token::NUMBER:
1383 Next();
1384 result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
1385 break;
1386
1387 case Token::IDENTIFIER:
1388 case Token::YIELD:
1389 case Token::FUTURE_STRICT_RESERVED_WORD: {
1390 // Using eval or arguments in this context is OK even in strict mode.
1391 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1392 result = this->ExpressionFromIdentifier(name, pos, scope_, factory());
1393 break;
1394 }
1395
1396 case Token::STRING: {
1397 Consume(Token::STRING);
1398 result = this->ExpressionFromString(pos, scanner(), factory());
1399 break;
1400 }
1401
1402 case Token::ASSIGN_DIV:
1403 result = this->ParseRegExpLiteral(true, CHECK_OK);
1404 break;
1405
1406 case Token::DIV:
1407 result = this->ParseRegExpLiteral(false, CHECK_OK);
1408 break;
1409
1410 case Token::LBRACK:
1411 result = this->ParseArrayLiteral(CHECK_OK);
1412 break;
1413
1414 case Token::LBRACE:
1415 result = this->ParseObjectLiteral(CHECK_OK);
1416 break;
1417
1418 case Token::LPAREN:
1419 Consume(Token::LPAREN);
1420 // Heuristically try to detect immediately called functions before
1421 // seeing the call parentheses.
1422 parenthesized_function_ = (peek() == Token::FUNCTION);
1423 result = this->ParseExpression(true, CHECK_OK);
1424 Expect(Token::RPAREN, CHECK_OK);
1425 break;
1426
1427 case Token::MOD:
1428 if (allow_natives_syntax() || extension_ != NULL) {
1429 result = this->ParseV8Intrinsic(CHECK_OK);
1430 break;
1431 }
1432 // If we're not allowing special syntax we fall-through to the
1433 // default case.
1434
1435 default: {
1436 Next();
1437 ReportUnexpectedToken(token);
1438 *ok = false;
1439 }
1440 }
1441
1442 return result;
1443 }
1444
1445 // Precedence = 1
1446 template <class Traits>
ParseExpression(bool accept_IN,bool * ok)1447 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
1448 bool accept_IN, bool* ok) {
1449 // Expression ::
1450 // AssignmentExpression
1451 // Expression ',' AssignmentExpression
1452
1453 ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1454 while (peek() == Token::COMMA) {
1455 Expect(Token::COMMA, CHECK_OK);
1456 int pos = position();
1457 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1458 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
1459 }
1460 return result;
1461 }
1462
1463
1464 template <class Traits>
ParseArrayLiteral(bool * ok)1465 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
1466 bool* ok) {
1467 // ArrayLiteral ::
1468 // '[' Expression? (',' Expression?)* ']'
1469
1470 int pos = peek_position();
1471 typename Traits::Type::ExpressionList values =
1472 this->NewExpressionList(4, zone_);
1473 Expect(Token::LBRACK, CHECK_OK);
1474 while (peek() != Token::RBRACK) {
1475 ExpressionT elem = this->EmptyExpression();
1476 if (peek() == Token::COMMA) {
1477 elem = this->GetLiteralTheHole(peek_position(), factory());
1478 } else {
1479 elem = this->ParseAssignmentExpression(true, CHECK_OK);
1480 }
1481 values->Add(elem, zone_);
1482 if (peek() != Token::RBRACK) {
1483 Expect(Token::COMMA, CHECK_OK);
1484 }
1485 }
1486 Expect(Token::RBRACK, CHECK_OK);
1487
1488 // Update the scope information before the pre-parsing bailout.
1489 int literal_index = function_state_->NextMaterializedLiteralIndex();
1490
1491 return factory()->NewArrayLiteral(values, literal_index, pos);
1492 }
1493
1494
1495 template <class Traits>
ParseObjectLiteral(bool * ok)1496 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
1497 bool* ok) {
1498 // ObjectLiteral ::
1499 // '{' ((
1500 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
1501 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1502 // ) ',')* '}'
1503 // (Except that trailing comma is not required and not allowed.)
1504
1505 int pos = peek_position();
1506 typename Traits::Type::PropertyList properties =
1507 this->NewPropertyList(4, zone_);
1508 int number_of_boilerplate_properties = 0;
1509 bool has_function = false;
1510
1511 ObjectLiteralChecker checker(this, strict_mode());
1512
1513 Expect(Token::LBRACE, CHECK_OK);
1514
1515 while (peek() != Token::RBRACE) {
1516 if (fni_ != NULL) fni_->Enter();
1517
1518 typename Traits::Type::Literal key = this->EmptyLiteral();
1519 Token::Value next = peek();
1520 int next_pos = peek_position();
1521
1522 switch (next) {
1523 case Token::FUTURE_RESERVED_WORD:
1524 case Token::FUTURE_STRICT_RESERVED_WORD:
1525 case Token::IDENTIFIER: {
1526 bool is_getter = false;
1527 bool is_setter = false;
1528 IdentifierT id =
1529 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1530 if (fni_ != NULL) this->PushLiteralName(fni_, id);
1531
1532 if ((is_getter || is_setter) && peek() != Token::COLON) {
1533 // Special handling of getter and setter syntax:
1534 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
1535 // We have already read the "get" or "set" keyword.
1536 Token::Value next = Next();
1537 if (next != i::Token::IDENTIFIER &&
1538 next != i::Token::FUTURE_RESERVED_WORD &&
1539 next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1540 next != i::Token::NUMBER &&
1541 next != i::Token::STRING &&
1542 !Token::IsKeyword(next)) {
1543 ReportUnexpectedToken(next);
1544 *ok = false;
1545 return this->EmptyLiteral();
1546 }
1547 // Validate the property.
1548 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
1549 checker.CheckProperty(next, type, CHECK_OK);
1550 IdentifierT name = this->GetSymbol(scanner_);
1551 typename Traits::Type::FunctionLiteral value =
1552 this->ParseFunctionLiteral(
1553 name, scanner()->location(),
1554 false, // reserved words are allowed here
1555 false, // not a generator
1556 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
1557 is_getter ? FunctionLiteral::GETTER_ARITY
1558 : FunctionLiteral::SETTER_ARITY,
1559 CHECK_OK);
1560 typename Traits::Type::ObjectLiteralProperty property =
1561 factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
1562 if (this->IsBoilerplateProperty(property)) {
1563 number_of_boilerplate_properties++;
1564 }
1565 properties->Add(property, zone());
1566 if (peek() != Token::RBRACE) {
1567 // Need {} because of the CHECK_OK macro.
1568 Expect(Token::COMMA, CHECK_OK);
1569 }
1570
1571 if (fni_ != NULL) {
1572 fni_->Infer();
1573 fni_->Leave();
1574 }
1575 continue; // restart the while
1576 }
1577 // Failed to parse as get/set property, so it's just a normal property
1578 // (which might be called "get" or "set" or something else).
1579 key = factory()->NewLiteral(id, next_pos);
1580 break;
1581 }
1582 case Token::STRING: {
1583 Consume(Token::STRING);
1584 IdentifierT string = this->GetSymbol(scanner_);
1585 if (fni_ != NULL) this->PushLiteralName(fni_, string);
1586 uint32_t index;
1587 if (this->IsArrayIndex(string, &index)) {
1588 key = factory()->NewNumberLiteral(index, next_pos);
1589 break;
1590 }
1591 key = factory()->NewLiteral(string, next_pos);
1592 break;
1593 }
1594 case Token::NUMBER: {
1595 Consume(Token::NUMBER);
1596 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
1597 factory());
1598 break;
1599 }
1600 default:
1601 if (Token::IsKeyword(next)) {
1602 Consume(next);
1603 IdentifierT string = this->GetSymbol(scanner_);
1604 key = factory()->NewLiteral(string, next_pos);
1605 } else {
1606 Token::Value next = Next();
1607 ReportUnexpectedToken(next);
1608 *ok = false;
1609 return this->EmptyLiteral();
1610 }
1611 }
1612
1613 // Validate the property
1614 checker.CheckProperty(next, kValueProperty, CHECK_OK);
1615
1616 Expect(Token::COLON, CHECK_OK);
1617 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK);
1618
1619 typename Traits::Type::ObjectLiteralProperty property =
1620 factory()->NewObjectLiteralProperty(key, value);
1621
1622 // Mark top-level object literals that contain function literals and
1623 // pretenure the literal so it can be added as a constant function
1624 // property. (Parser only.)
1625 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value,
1626 &has_function);
1627
1628 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
1629 if (this->IsBoilerplateProperty(property)) {
1630 number_of_boilerplate_properties++;
1631 }
1632 properties->Add(property, zone());
1633
1634 // TODO(1240767): Consider allowing trailing comma.
1635 if (peek() != Token::RBRACE) {
1636 // Need {} because of the CHECK_OK macro.
1637 Expect(Token::COMMA, CHECK_OK);
1638 }
1639
1640 if (fni_ != NULL) {
1641 fni_->Infer();
1642 fni_->Leave();
1643 }
1644 }
1645 Expect(Token::RBRACE, CHECK_OK);
1646
1647 // Computation of literal_index must happen before pre parse bailout.
1648 int literal_index = function_state_->NextMaterializedLiteralIndex();
1649
1650 return factory()->NewObjectLiteral(properties,
1651 literal_index,
1652 number_of_boilerplate_properties,
1653 has_function,
1654 pos);
1655 }
1656
1657
1658 template <class Traits>
ParseArguments(bool * ok)1659 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
1660 bool* ok) {
1661 // Arguments ::
1662 // '(' (AssignmentExpression)*[','] ')'
1663
1664 typename Traits::Type::ExpressionList result =
1665 this->NewExpressionList(4, zone_);
1666 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
1667 bool done = (peek() == Token::RPAREN);
1668 while (!done) {
1669 ExpressionT argument = this->ParseAssignmentExpression(
1670 true, CHECK_OK_CUSTOM(NullExpressionList));
1671 result->Add(argument, zone_);
1672 if (result->length() > Code::kMaxArguments) {
1673 ReportMessage("too_many_arguments");
1674 *ok = false;
1675 return this->NullExpressionList();
1676 }
1677 done = (peek() == Token::RPAREN);
1678 if (!done) {
1679 // Need {} because of the CHECK_OK_CUSTOM macro.
1680 Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList));
1681 }
1682 }
1683 Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
1684 return result;
1685 }
1686
1687 // Precedence = 2
1688 template <class Traits>
1689 typename ParserBase<Traits>::ExpressionT
ParseAssignmentExpression(bool accept_IN,bool * ok)1690 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
1691 // AssignmentExpression ::
1692 // ConditionalExpression
1693 // YieldExpression
1694 // LeftHandSideExpression AssignmentOperator AssignmentExpression
1695
1696 Scanner::Location lhs_location = scanner()->peek_location();
1697
1698 if (peek() == Token::YIELD && is_generator()) {
1699 return this->ParseYieldExpression(ok);
1700 }
1701
1702 if (fni_ != NULL) fni_->Enter();
1703 ExpressionT expression =
1704 this->ParseConditionalExpression(accept_IN, CHECK_OK);
1705
1706 if (!Token::IsAssignmentOp(peek())) {
1707 if (fni_ != NULL) fni_->Leave();
1708 // Parsed conditional expression only (no assignment).
1709 return expression;
1710 }
1711
1712 expression = this->CheckAndRewriteReferenceExpression(
1713 expression, lhs_location, "invalid_lhs_in_assignment", CHECK_OK);
1714 expression = this->MarkExpressionAsLValue(expression);
1715
1716 Token::Value op = Next(); // Get assignment operator.
1717 int pos = position();
1718 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1719
1720 // TODO(1231235): We try to estimate the set of properties set by
1721 // constructors. We define a new property whenever there is an
1722 // assignment to a property of 'this'. We should probably only add
1723 // properties if we haven't seen them before. Otherwise we'll
1724 // probably overestimate the number of properties.
1725 if (op == Token::ASSIGN && this->IsThisProperty(expression)) {
1726 function_state_->AddProperty();
1727 }
1728
1729 this->CheckAssigningFunctionLiteralToProperty(expression, right);
1730
1731 if (fni_ != NULL) {
1732 // Check if the right hand side is a call to avoid inferring a
1733 // name if we're dealing with "a = function(){...}();"-like
1734 // expression.
1735 if ((op == Token::INIT_VAR
1736 || op == Token::INIT_CONST_LEGACY
1737 || op == Token::ASSIGN)
1738 && (!right->IsCall() && !right->IsCallNew())) {
1739 fni_->Infer();
1740 } else {
1741 fni_->RemoveLastFunction();
1742 }
1743 fni_->Leave();
1744 }
1745
1746 return factory()->NewAssignment(op, expression, right, pos);
1747 }
1748
1749 template <class Traits>
1750 typename ParserBase<Traits>::ExpressionT
ParseYieldExpression(bool * ok)1751 ParserBase<Traits>::ParseYieldExpression(bool* ok) {
1752 // YieldExpression ::
1753 // 'yield' '*'? AssignmentExpression
1754 int pos = peek_position();
1755 Expect(Token::YIELD, CHECK_OK);
1756 Yield::Kind kind =
1757 Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
1758 ExpressionT generator_object =
1759 factory()->NewVariableProxy(function_state_->generator_object_variable());
1760 ExpressionT expression =
1761 ParseAssignmentExpression(false, CHECK_OK);
1762 typename Traits::Type::YieldExpression yield =
1763 factory()->NewYield(generator_object, expression, kind, pos);
1764 if (kind == Yield::DELEGATING) {
1765 yield->set_index(function_state_->NextHandlerIndex());
1766 }
1767 return yield;
1768 }
1769
1770
1771 // Precedence = 3
1772 template <class Traits>
1773 typename ParserBase<Traits>::ExpressionT
ParseConditionalExpression(bool accept_IN,bool * ok)1774 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
1775 // ConditionalExpression ::
1776 // LogicalOrExpression
1777 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
1778
1779 int pos = peek_position();
1780 // We start using the binary expression parser for prec >= 4 only!
1781 ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK);
1782 if (peek() != Token::CONDITIONAL) return expression;
1783 Consume(Token::CONDITIONAL);
1784 // In parsing the first assignment expression in conditional
1785 // expressions we always accept the 'in' keyword; see ECMA-262,
1786 // section 11.12, page 58.
1787 ExpressionT left = ParseAssignmentExpression(true, CHECK_OK);
1788 Expect(Token::COLON, CHECK_OK);
1789 ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK);
1790 return factory()->NewConditional(expression, left, right, pos);
1791 }
1792
1793
1794 // Precedence >= 4
1795 template <class Traits>
1796 typename ParserBase<Traits>::ExpressionT
ParseBinaryExpression(int prec,bool accept_IN,bool * ok)1797 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
1798 ASSERT(prec >= 4);
1799 ExpressionT x = this->ParseUnaryExpression(CHECK_OK);
1800 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
1801 // prec1 >= 4
1802 while (Precedence(peek(), accept_IN) == prec1) {
1803 Token::Value op = Next();
1804 int pos = position();
1805 ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
1806
1807 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
1808 factory())) {
1809 continue;
1810 }
1811
1812 // For now we distinguish between comparisons and other binary
1813 // operations. (We could combine the two and get rid of this
1814 // code and AST node eventually.)
1815 if (Token::IsCompareOp(op)) {
1816 // We have a comparison.
1817 Token::Value cmp = op;
1818 switch (op) {
1819 case Token::NE: cmp = Token::EQ; break;
1820 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
1821 default: break;
1822 }
1823 x = factory()->NewCompareOperation(cmp, x, y, pos);
1824 if (cmp != op) {
1825 // The comparison was negated - add a NOT.
1826 x = factory()->NewUnaryOperation(Token::NOT, x, pos);
1827 }
1828
1829 } else {
1830 // We have a "normal" binary operation.
1831 x = factory()->NewBinaryOperation(op, x, y, pos);
1832 }
1833 }
1834 }
1835 return x;
1836 }
1837
1838
1839 template <class Traits>
1840 typename ParserBase<Traits>::ExpressionT
ParseUnaryExpression(bool * ok)1841 ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
1842 // UnaryExpression ::
1843 // PostfixExpression
1844 // 'delete' UnaryExpression
1845 // 'void' UnaryExpression
1846 // 'typeof' UnaryExpression
1847 // '++' UnaryExpression
1848 // '--' UnaryExpression
1849 // '+' UnaryExpression
1850 // '-' UnaryExpression
1851 // '~' UnaryExpression
1852 // '!' UnaryExpression
1853
1854 Token::Value op = peek();
1855 if (Token::IsUnaryOp(op)) {
1856 op = Next();
1857 int pos = position();
1858 ExpressionT expression = ParseUnaryExpression(CHECK_OK);
1859
1860 // "delete identifier" is a syntax error in strict mode.
1861 if (op == Token::DELETE && strict_mode() == STRICT &&
1862 this->IsIdentifier(expression)) {
1863 ReportMessage("strict_delete");
1864 *ok = false;
1865 return this->EmptyExpression();
1866 }
1867
1868 // Allow Traits do rewrite the expression.
1869 return this->BuildUnaryExpression(expression, op, pos, factory());
1870 } else if (Token::IsCountOp(op)) {
1871 op = Next();
1872 Scanner::Location lhs_location = scanner()->peek_location();
1873 ExpressionT expression = this->ParseUnaryExpression(CHECK_OK);
1874 expression = this->CheckAndRewriteReferenceExpression(
1875 expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK);
1876 this->MarkExpressionAsLValue(expression);
1877
1878 return factory()->NewCountOperation(op,
1879 true /* prefix */,
1880 expression,
1881 position());
1882
1883 } else {
1884 return this->ParsePostfixExpression(ok);
1885 }
1886 }
1887
1888
1889 template <class Traits>
1890 typename ParserBase<Traits>::ExpressionT
ParsePostfixExpression(bool * ok)1891 ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
1892 // PostfixExpression ::
1893 // LeftHandSideExpression ('++' | '--')?
1894
1895 Scanner::Location lhs_location = scanner()->peek_location();
1896 ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK);
1897 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
1898 Token::IsCountOp(peek())) {
1899 expression = this->CheckAndRewriteReferenceExpression(
1900 expression, lhs_location, "invalid_lhs_in_postfix_op", CHECK_OK);
1901 expression = this->MarkExpressionAsLValue(expression);
1902
1903 Token::Value next = Next();
1904 expression =
1905 factory()->NewCountOperation(next,
1906 false /* postfix */,
1907 expression,
1908 position());
1909 }
1910 return expression;
1911 }
1912
1913
1914 template <class Traits>
1915 typename ParserBase<Traits>::ExpressionT
ParseLeftHandSideExpression(bool * ok)1916 ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
1917 // LeftHandSideExpression ::
1918 // (NewExpression | MemberExpression) ...
1919
1920 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
1921
1922 while (true) {
1923 switch (peek()) {
1924 case Token::LBRACK: {
1925 Consume(Token::LBRACK);
1926 int pos = position();
1927 ExpressionT index = ParseExpression(true, CHECK_OK);
1928 result = factory()->NewProperty(result, index, pos);
1929 Expect(Token::RBRACK, CHECK_OK);
1930 break;
1931 }
1932
1933 case Token::LPAREN: {
1934 int pos;
1935 if (scanner()->current_token() == Token::IDENTIFIER) {
1936 // For call of an identifier we want to report position of
1937 // the identifier as position of the call in the stack trace.
1938 pos = position();
1939 } else {
1940 // For other kinds of calls we record position of the parenthesis as
1941 // position of the call. Note that this is extremely important for
1942 // expressions of the form function(){...}() for which call position
1943 // should not point to the closing brace otherwise it will intersect
1944 // with positions recorded for function literal and confuse debugger.
1945 pos = peek_position();
1946 // Also the trailing parenthesis are a hint that the function will
1947 // be called immediately. If we happen to have parsed a preceding
1948 // function literal eagerly, we can also compile it eagerly.
1949 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
1950 result->AsFunctionLiteral()->set_parenthesized();
1951 }
1952 }
1953 typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK);
1954
1955 // Keep track of eval() calls since they disable all local variable
1956 // optimizations.
1957 // The calls that need special treatment are the
1958 // direct eval calls. These calls are all of the form eval(...), with
1959 // no explicit receiver.
1960 // These calls are marked as potentially direct eval calls. Whether
1961 // they are actually direct calls to eval is determined at run time.
1962 this->CheckPossibleEvalCall(result, scope_);
1963 result = factory()->NewCall(result, args, pos);
1964 if (fni_ != NULL) fni_->RemoveLastFunction();
1965 break;
1966 }
1967
1968 case Token::PERIOD: {
1969 Consume(Token::PERIOD);
1970 int pos = position();
1971 IdentifierT name = ParseIdentifierName(CHECK_OK);
1972 result = factory()->NewProperty(
1973 result, factory()->NewLiteral(name, pos), pos);
1974 if (fni_ != NULL) this->PushLiteralName(fni_, name);
1975 break;
1976 }
1977
1978 default:
1979 return result;
1980 }
1981 }
1982 }
1983
1984
1985 template <class Traits>
1986 typename ParserBase<Traits>::ExpressionT
ParseMemberWithNewPrefixesExpression(bool * ok)1987 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
1988 // NewExpression ::
1989 // ('new')+ MemberExpression
1990
1991 // The grammar for new expressions is pretty warped. We can have several 'new'
1992 // keywords following each other, and then a MemberExpression. When we see '('
1993 // after the MemberExpression, it's associated with the rightmost unassociated
1994 // 'new' to create a NewExpression with arguments. However, a NewExpression
1995 // can also occur without arguments.
1996
1997 // Examples of new expression:
1998 // new foo.bar().baz means (new (foo.bar)()).baz
1999 // new foo()() means (new foo())()
2000 // new new foo()() means (new (new foo())())
2001 // new new foo means new (new foo)
2002 // new new foo() means new (new foo())
2003 // new new foo().bar().baz means (new (new foo()).bar()).baz
2004
2005 if (peek() == Token::NEW) {
2006 Consume(Token::NEW);
2007 int new_pos = position();
2008 ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
2009 if (peek() == Token::LPAREN) {
2010 // NewExpression with arguments.
2011 typename Traits::Type::ExpressionList args =
2012 this->ParseArguments(CHECK_OK);
2013 result = factory()->NewCallNew(result, args, new_pos);
2014 // The expression can still continue with . or [ after the arguments.
2015 result = this->ParseMemberExpressionContinuation(result, CHECK_OK);
2016 return result;
2017 }
2018 // NewExpression without arguments.
2019 return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
2020 new_pos);
2021 }
2022 // No 'new' keyword.
2023 return this->ParseMemberExpression(ok);
2024 }
2025
2026
2027 template <class Traits>
2028 typename ParserBase<Traits>::ExpressionT
ParseMemberExpression(bool * ok)2029 ParserBase<Traits>::ParseMemberExpression(bool* ok) {
2030 // MemberExpression ::
2031 // (PrimaryExpression | FunctionLiteral)
2032 // ('[' Expression ']' | '.' Identifier | Arguments)*
2033
2034 // The '[' Expression ']' and '.' Identifier parts are parsed by
2035 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
2036 // caller.
2037
2038 // Parse the initial primary or function expression.
2039 ExpressionT result = this->EmptyExpression();
2040 if (peek() == Token::FUNCTION) {
2041 Consume(Token::FUNCTION);
2042 int function_token_position = position();
2043 bool is_generator = allow_generators() && Check(Token::MUL);
2044 IdentifierT name = this->EmptyIdentifier();
2045 bool is_strict_reserved_name = false;
2046 Scanner::Location function_name_location = Scanner::Location::invalid();
2047 FunctionLiteral::FunctionType function_type =
2048 FunctionLiteral::ANONYMOUS_EXPRESSION;
2049 if (peek_any_identifier()) {
2050 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
2051 CHECK_OK);
2052 function_name_location = scanner()->location();
2053 function_type = FunctionLiteral::NAMED_EXPRESSION;
2054 }
2055 result = this->ParseFunctionLiteral(name,
2056 function_name_location,
2057 is_strict_reserved_name,
2058 is_generator,
2059 function_token_position,
2060 function_type,
2061 FunctionLiteral::NORMAL_ARITY,
2062 CHECK_OK);
2063 } else {
2064 result = ParsePrimaryExpression(CHECK_OK);
2065 }
2066
2067 result = ParseMemberExpressionContinuation(result, CHECK_OK);
2068 return result;
2069 }
2070
2071
2072 template <class Traits>
2073 typename ParserBase<Traits>::ExpressionT
ParseMemberExpressionContinuation(ExpressionT expression,bool * ok)2074 ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
2075 bool* ok) {
2076 // Parses this part of MemberExpression:
2077 // ('[' Expression ']' | '.' Identifier)*
2078 while (true) {
2079 switch (peek()) {
2080 case Token::LBRACK: {
2081 Consume(Token::LBRACK);
2082 int pos = position();
2083 ExpressionT index = this->ParseExpression(true, CHECK_OK);
2084 expression = factory()->NewProperty(expression, index, pos);
2085 if (fni_ != NULL) {
2086 this->PushPropertyName(fni_, index);
2087 }
2088 Expect(Token::RBRACK, CHECK_OK);
2089 break;
2090 }
2091 case Token::PERIOD: {
2092 Consume(Token::PERIOD);
2093 int pos = position();
2094 IdentifierT name = ParseIdentifierName(CHECK_OK);
2095 expression = factory()->NewProperty(
2096 expression, factory()->NewLiteral(name, pos), pos);
2097 if (fni_ != NULL) {
2098 this->PushLiteralName(fni_, name);
2099 }
2100 break;
2101 }
2102 default:
2103 return expression;
2104 }
2105 }
2106 ASSERT(false);
2107 return this->EmptyExpression();
2108 }
2109
2110
2111 template <typename Traits>
2112 typename ParserBase<Traits>::ExpressionT
CheckAndRewriteReferenceExpression(ExpressionT expression,Scanner::Location location,const char * message,bool * ok)2113 ParserBase<Traits>::CheckAndRewriteReferenceExpression(
2114 ExpressionT expression,
2115 Scanner::Location location, const char* message, bool* ok) {
2116 if (strict_mode() == STRICT && this->IsIdentifier(expression) &&
2117 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
2118 this->ReportMessageAt(location, "strict_eval_arguments", false);
2119 *ok = false;
2120 return this->EmptyExpression();
2121 } else if (expression->IsValidReferenceExpression()) {
2122 return expression;
2123 } else if (expression->IsCall()) {
2124 // If it is a call, make it a runtime error for legacy web compatibility.
2125 // Rewrite `expr' to `expr[throw ReferenceError]'.
2126 int pos = location.beg_pos;
2127 ExpressionT error = this->NewThrowReferenceError(message, pos);
2128 return factory()->NewProperty(expression, error, pos);
2129 } else {
2130 this->ReportMessageAt(location, message, true);
2131 *ok = false;
2132 return this->EmptyExpression();
2133 }
2134 }
2135
2136
2137 #undef CHECK_OK
2138 #undef CHECK_OK_CUSTOM
2139
2140
2141 template <typename Traits>
CheckProperty(Token::Value property,PropertyKind type,bool * ok)2142 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
2143 Token::Value property,
2144 PropertyKind type,
2145 bool* ok) {
2146 int old;
2147 if (property == Token::NUMBER) {
2148 old = scanner()->FindNumber(&finder_, type);
2149 } else {
2150 old = scanner()->FindSymbol(&finder_, type);
2151 }
2152 PropertyKind old_type = static_cast<PropertyKind>(old);
2153 if (HasConflict(old_type, type)) {
2154 if (IsDataDataConflict(old_type, type)) {
2155 // Both are data properties.
2156 if (strict_mode_ == SLOPPY) return;
2157 parser()->ReportMessage("strict_duplicate_property");
2158 } else if (IsDataAccessorConflict(old_type, type)) {
2159 // Both a data and an accessor property with the same name.
2160 parser()->ReportMessage("accessor_data_property");
2161 } else {
2162 ASSERT(IsAccessorAccessorConflict(old_type, type));
2163 // Both accessors of the same type.
2164 parser()->ReportMessage("accessor_get_set");
2165 }
2166 *ok = false;
2167 }
2168 }
2169
2170
2171 } } // v8::internal
2172
2173 #endif // V8_PREPARSER_H
2174