blob: e99b4b0a181e200030100aa10446cfa2cb7bf923 [file] [log] [blame]
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +00001// Copyright 2012 the V8 project authors. All rights reserved.
lrn@chromium.orgfa943b72010-11-03 08:14:36 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_PREPARSER_H
29#define V8_PREPARSER_H
30
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000031#include "hashmap.h"
ricow@chromium.org55ee8072011-09-08 16:33:10 +000032#include "token.h"
33#include "scanner.h"
34
lrn@chromium.orgfa943b72010-11-03 08:14:36 +000035namespace v8 {
ricow@chromium.org55ee8072011-09-08 16:33:10 +000036namespace internal {
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +000037
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000038// Common base class shared between parser and pre-parser.
39class ParserBase {
40 public:
41 ParserBase(Scanner* scanner, uintptr_t stack_limit)
42 : scanner_(scanner),
43 stack_limit_(stack_limit),
44 stack_overflow_(false),
45 allow_lazy_(false),
46 allow_natives_syntax_(false),
47 allow_generators_(false),
48 allow_for_of_(false) { }
49 // TODO(mstarzinger): Only virtual until message reporting has been unified.
50 virtual ~ParserBase() { }
lrn@chromium.orgfa943b72010-11-03 08:14:36 +000051
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000052 // Getters that indicate whether certain syntactical constructs are
53 // allowed to be parsed by this instance of the parser.
54 bool allow_lazy() const { return allow_lazy_; }
55 bool allow_natives_syntax() const { return allow_natives_syntax_; }
56 bool allow_generators() const { return allow_generators_; }
57 bool allow_for_of() const { return allow_for_of_; }
58 bool allow_modules() const { return scanner()->HarmonyModules(); }
59 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
60 bool allow_harmony_numeric_literals() const {
61 return scanner()->HarmonyNumericLiterals();
62 }
63
64 // Setters that determine whether certain syntactical constructs are
65 // allowed to be parsed by this instance of the parser.
66 void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
67 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
68 void set_allow_generators(bool allow) { allow_generators_ = allow; }
69 void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
70 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
71 void set_allow_harmony_scoping(bool allow) {
72 scanner()->SetHarmonyScoping(allow);
73 }
74 void set_allow_harmony_numeric_literals(bool allow) {
75 scanner()->SetHarmonyNumericLiterals(allow);
76 }
77
78 protected:
79 Scanner* scanner() const { return scanner_; }
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000080 int position() { return scanner_->location().beg_pos; }
81 int peek_position() { return scanner_->peek_location().beg_pos; }
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000082 bool stack_overflow() const { return stack_overflow_; }
83 void set_stack_overflow() { stack_overflow_ = true; }
84
85 INLINE(Token::Value peek()) {
86 if (stack_overflow_) return Token::ILLEGAL;
87 return scanner()->peek();
88 }
89
90 INLINE(Token::Value Next()) {
91 if (stack_overflow_) return Token::ILLEGAL;
92 {
93 int marker;
94 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
95 // Any further calls to Next or peek will return the illegal token.
96 // The current call must return the next token, which might already
97 // have been peek'ed.
98 stack_overflow_ = true;
99 }
100 }
101 return scanner()->Next();
102 }
103
104 void Consume(Token::Value token) {
105 Token::Value next = Next();
106 USE(next);
107 USE(token);
108 ASSERT(next == token);
109 }
110
111 bool Check(Token::Value token) {
112 Token::Value next = peek();
113 if (next == token) {
114 Consume(next);
115 return true;
116 }
117 return false;
118 }
119
120 void Expect(Token::Value token, bool* ok) {
121 Token::Value next = Next();
122 if (next != token) {
123 ReportUnexpectedToken(next);
124 *ok = false;
125 }
126 }
127
128 bool peek_any_identifier();
129 void ExpectSemicolon(bool* ok);
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000130 bool CheckContextualKeyword(Vector<const char> keyword);
131 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok);
132
133 // Strict mode octal literal validation.
134 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
135
136 // Determine precedence of given token.
137 static int Precedence(Token::Value token, bool accept_IN);
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000138
139 // Report syntax errors.
140 virtual void ReportUnexpectedToken(Token::Value token) = 0;
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000141 virtual void ReportMessageAt(Scanner::Location loc, const char* type) = 0;
142
143 // Used to detect duplicates in object literals. Each of the values
144 // kGetterProperty, kSetterProperty and kValueProperty represents
145 // a type of object literal property. When parsing a property, its
146 // type value is stored in the DuplicateFinder for the property name.
147 // Values are chosen so that having intersection bits means the there is
148 // an incompatibility.
149 // I.e., you can add a getter to a property that already has a setter, since
150 // kGetterProperty and kSetterProperty doesn't intersect, but not if it
151 // already has a getter or a value. Adding the getter to an existing
152 // setter will store the value (kGetterProperty | kSetterProperty), which
153 // is incompatible with adding any further properties.
154 enum PropertyKind {
155 kNone = 0,
156 // Bit patterns representing different object literal property types.
157 kGetterProperty = 1,
158 kSetterProperty = 2,
159 kValueProperty = 7,
160 // Helper constants.
161 kValueFlag = 4
162 };
163
164 // Validation per ECMA 262 - 11.1.5 "Object Initialiser".
165 class ObjectLiteralChecker {
166 public:
167 ObjectLiteralChecker(ParserBase* parser, LanguageMode mode)
168 : parser_(parser),
169 finder_(scanner()->unicode_cache()),
170 language_mode_(mode) { }
171
172 void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
173
174 private:
175 ParserBase* parser() const { return parser_; }
176 Scanner* scanner() const { return parser_->scanner(); }
177
178 // Checks the type of conflict based on values coming from PropertyType.
179 bool HasConflict(PropertyKind type1, PropertyKind type2) {
180 return (type1 & type2) != 0;
181 }
182 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
183 return ((type1 & type2) & kValueFlag) != 0;
184 }
185 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
186 return ((type1 ^ type2) & kValueFlag) != 0;
187 }
188 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
189 return ((type1 | type2) & kValueFlag) == 0;
190 }
191
192 ParserBase* parser_;
193 DuplicateFinder finder_;
194 LanguageMode language_mode_;
195 };
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000196
197 private:
198 Scanner* scanner_;
199 uintptr_t stack_limit_;
200 bool stack_overflow_;
201
202 bool allow_lazy_;
203 bool allow_natives_syntax_;
204 bool allow_generators_;
205 bool allow_for_of_;
206};
207
ricow@chromium.org55ee8072011-09-08 16:33:10 +0000208
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000209// Preparsing checks a JavaScript program and emits preparse-data that helps
210// a later parsing to be faster.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000211// See preparse-data-format.h for the data format.
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000212
213// The PreParser checks that the syntax follows the grammar for JavaScript,
214// and collects some information about the program along the way.
215// The grammar check is only performed in order to understand the program
216// sufficiently to deduce some information about it, that can be used
217// to speed up later parsing. Finding errors is not the goal of pre-parsing,
218// rather it is to speed up properly written and correct programs.
219// That means that contextual checks (like a label being declared where
220// it is used) are generally omitted.
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000221class PreParser : public ParserBase {
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000222 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000223 enum PreParseResult {
224 kPreParseStackOverflow,
225 kPreParseSuccess
226 };
227
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000228 PreParser(Scanner* scanner,
229 ParserRecorder* log,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000230 uintptr_t stack_limit)
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000231 : ParserBase(scanner, stack_limit),
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000232 log_(log),
233 scope_(NULL),
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000234 strict_mode_violation_location_(Scanner::Location::invalid()),
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000235 strict_mode_violation_type_(NULL),
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000236 parenthesized_function_(false) { }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000237
ricow@chromium.org55ee8072011-09-08 16:33:10 +0000238 ~PreParser() {}
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000239
240 // Pre-parse the program from the character stream; returns true on
241 // success (even if parsing failed, the pre-parse data successfully
242 // captured the syntax error), and false if a stack-overflow happened
243 // during parsing.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000244 PreParseResult PreParseProgram() {
245 Scope top_scope(&scope_, kTopLevelScope);
246 bool ok = true;
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000247 int start_position = scanner()->peek_location().beg_pos;
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000248 ParseSourceElements(Token::EOS, &ok);
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000249 if (stack_overflow()) return kPreParseStackOverflow;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000250 if (!ok) {
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000251 ReportUnexpectedToken(scanner()->current_token());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000252 } else if (!scope_->is_classic_mode()) {
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000253 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000254 }
255 return kPreParseSuccess;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000256 }
257
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000258 // Parses a single function literal, from the opening parentheses before
259 // parameters to the closing brace after the body.
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +0000260 // Returns a FunctionEntry describing the body of the function in enough
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000261 // detail that it can be lazily compiled.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000262 // The scanner is expected to have matched the "function" or "function*"
263 // keyword and parameters, and have consumed the initial '{'.
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +0000264 // At return, unless an error occurred, the scanner is positioned before the
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000265 // the final '}'.
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000266 PreParseResult PreParseLazyFunction(LanguageMode mode,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000267 bool is_generator,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000268 ParserRecorder* log);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000269
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000270 private:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000271 // These types form an algebra over syntactic categories that is just
272 // rich enough to let us recognize and propagate the constructs that
273 // are either being counted in the preparser data, or is important
274 // to throw the correct syntax error exceptions.
275
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000276 enum ScopeType {
277 kTopLevelScope,
278 kFunctionScope
279 };
280
danno@chromium.orgb6451162011-08-17 14:33:23 +0000281 enum VariableDeclarationContext {
282 kSourceElement,
283 kStatement,
284 kForStatement
285 };
286
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000287 // If a list of variable declarations includes any initializers.
288 enum VariableDeclarationProperties {
289 kHasInitializers,
290 kHasNoInitializers
291 };
292
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000293 class Expression;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000294
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000295 class Identifier {
296 public:
297 static Identifier Default() {
298 return Identifier(kUnknownIdentifier);
299 }
300 static Identifier Eval() {
301 return Identifier(kEvalIdentifier);
302 }
303 static Identifier Arguments() {
304 return Identifier(kArgumentsIdentifier);
305 }
306 static Identifier FutureReserved() {
307 return Identifier(kFutureReservedIdentifier);
308 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000309 static Identifier FutureStrictReserved() {
310 return Identifier(kFutureStrictReservedIdentifier);
311 }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000312 static Identifier Yield() {
313 return Identifier(kYieldIdentifier);
314 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000315 bool IsEval() { return type_ == kEvalIdentifier; }
316 bool IsArguments() { return type_ == kArgumentsIdentifier; }
317 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000318 bool IsYield() { return type_ == kYieldIdentifier; }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000319 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
ager@chromium.org04921a82011-06-27 13:21:41 +0000320 bool IsFutureStrictReserved() {
321 return type_ == kFutureStrictReservedIdentifier;
322 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000323 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000324
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000325 private:
326 enum Type {
327 kUnknownIdentifier,
328 kFutureReservedIdentifier,
ager@chromium.org04921a82011-06-27 13:21:41 +0000329 kFutureStrictReservedIdentifier,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000330 kYieldIdentifier,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000331 kEvalIdentifier,
332 kArgumentsIdentifier
333 };
334 explicit Identifier(Type type) : type_(type) { }
335 Type type_;
336
337 friend class Expression;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000338 };
339
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000340 // Bits 0 and 1 are used to identify the type of expression:
341 // If bit 0 is set, it's an identifier.
342 // if bit 1 is set, it's a string literal.
343 // If neither is set, it's no particular type, and both set isn't
344 // use yet.
345 // Bit 2 is used to mark the expression as being parenthesized,
346 // so "(foo)" isn't recognized as a pure identifier (and possible label).
347 class Expression {
348 public:
349 static Expression Default() {
350 return Expression(kUnknownExpression);
351 }
352
353 static Expression FromIdentifier(Identifier id) {
354 return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift));
355 }
356
357 static Expression StringLiteral() {
358 return Expression(kUnknownStringLiteral);
359 }
360
361 static Expression UseStrictStringLiteral() {
362 return Expression(kUseStrictString);
363 }
364
365 static Expression This() {
366 return Expression(kThisExpression);
367 }
368
369 static Expression ThisProperty() {
370 return Expression(kThisPropertyExpression);
371 }
372
373 static Expression StrictFunction() {
374 return Expression(kStrictFunctionExpression);
375 }
376
377 bool IsIdentifier() {
378 return (code_ & kIdentifierFlag) != 0;
379 }
380
381 // Only works corretly if it is actually an identifier expression.
382 PreParser::Identifier AsIdentifier() {
383 return PreParser::Identifier(
384 static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift));
385 }
386
387 bool IsParenthesized() {
388 // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized.
389 return (code_ & 7) > 4;
390 }
391
392 bool IsRawIdentifier() {
393 return !IsParenthesized() && IsIdentifier();
394 }
395
396 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
397
398 bool IsRawStringLiteral() {
399 return !IsParenthesized() && IsStringLiteral();
400 }
401
402 bool IsUseStrictLiteral() {
403 return (code_ & kStringLiteralMask) == kUseStrictString;
404 }
405
406 bool IsThis() {
407 return code_ == kThisExpression;
408 }
409
410 bool IsThisProperty() {
411 return code_ == kThisPropertyExpression;
412 }
413
414 bool IsStrictFunction() {
415 return code_ == kStrictFunctionExpression;
416 }
417
418 Expression Parenthesize() {
419 int type = code_ & 3;
420 if (type != 0) {
421 // Identifiers and string literals can be parenthesized.
422 // They no longer work as labels or directive prologues,
423 // but are still recognized in other contexts.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000424 return Expression(code_ | kParenthesizedExpressionFlag);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000425 }
426 // For other types of expressions, it's not important to remember
427 // the parentheses.
428 return *this;
429 }
430
431 private:
432 // First two/three bits are used as flags.
433 // Bit 0 and 1 represent identifiers or strings literals, and are
434 // mutually exclusive, but can both be absent.
435 // If bit 0 or 1 are set, bit 2 marks that the expression has
436 // been wrapped in parentheses (a string literal can no longer
437 // be a directive prologue, and an identifier can no longer be
438 // a label.
439 enum {
440 kUnknownExpression = 0,
441 // Identifiers
442 kIdentifierFlag = 1, // Used to detect labels.
443 kIdentifierShift = 3,
444
445 kStringLiteralFlag = 2, // Used to detect directive prologue.
446 kUnknownStringLiteral = kStringLiteralFlag,
447 kUseStrictString = kStringLiteralFlag | 8,
448 kStringLiteralMask = kUseStrictString,
449
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000450 // Only if identifier or string literal.
451 kParenthesizedExpressionFlag = 4,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000452
453 // Below here applies if neither identifier nor string literal.
454 kThisExpression = 4,
455 kThisPropertyExpression = 8,
456 kStrictFunctionExpression = 12
457 };
458
459 explicit Expression(int expression_code) : code_(expression_code) { }
460
461 int code_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000462 };
463
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000464 class Statement {
465 public:
466 static Statement Default() {
467 return Statement(kUnknownStatement);
468 }
469
danno@chromium.org40cb8782011-05-25 07:58:50 +0000470 static Statement FunctionDeclaration() {
471 return Statement(kFunctionDeclaration);
472 }
473
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000474 // Creates expression statement from expression.
475 // Preserves being an unparenthesized string literal, possibly
476 // "use strict".
477 static Statement ExpressionStatement(Expression expression) {
478 if (!expression.IsParenthesized()) {
479 if (expression.IsUseStrictLiteral()) {
480 return Statement(kUseStrictExpressionStatement);
481 }
482 if (expression.IsStringLiteral()) {
483 return Statement(kStringLiteralExpressionStatement);
484 }
485 }
486 return Default();
487 }
488
489 bool IsStringLiteral() {
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +0000490 return code_ == kStringLiteralExpressionStatement;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000491 }
492
493 bool IsUseStrictLiteral() {
494 return code_ == kUseStrictExpressionStatement;
495 }
496
danno@chromium.org40cb8782011-05-25 07:58:50 +0000497 bool IsFunctionDeclaration() {
498 return code_ == kFunctionDeclaration;
499 }
500
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000501 private:
502 enum Type {
503 kUnknownStatement,
504 kStringLiteralExpressionStatement,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000505 kUseStrictExpressionStatement,
506 kFunctionDeclaration
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000507 };
508
509 explicit Statement(Type code) : code_(code) {}
510 Type code_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000511 };
512
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000513 enum SourceElements {
514 kUnknownSourceElements
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000515 };
516
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000517 typedef int Arguments;
518
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000519 class Scope {
520 public:
521 Scope(Scope** variable, ScopeType type)
522 : variable_(variable),
523 prev_(*variable),
524 type_(type),
525 materialized_literal_count_(0),
526 expected_properties_(0),
lrn@chromium.org1c092762011-05-09 09:42:16 +0000527 with_nesting_count_(0),
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000528 language_mode_(
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000529 (prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE),
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000530 is_generator_(false) {
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000531 *variable = this;
532 }
533 ~Scope() { *variable_ = prev_; }
534 void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
535 void AddProperty() { expected_properties_++; }
536 ScopeType type() { return type_; }
537 int expected_properties() { return expected_properties_; }
538 int materialized_literal_count() { return materialized_literal_count_; }
539 bool IsInsideWith() { return with_nesting_count_ != 0; }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000540 bool is_generator() { return is_generator_; }
541 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000542 bool is_classic_mode() {
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000543 return language_mode_ == CLASSIC_MODE;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000544 }
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000545 LanguageMode language_mode() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000546 return language_mode_;
547 }
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000548 void set_language_mode(LanguageMode language_mode) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000549 language_mode_ = language_mode;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000550 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +0000551
552 class InsideWith {
553 public:
554 explicit InsideWith(Scope* scope) : scope_(scope) {
555 scope->with_nesting_count_++;
556 }
557
558 ~InsideWith() { scope_->with_nesting_count_--; }
559
560 private:
561 Scope* scope_;
562 DISALLOW_COPY_AND_ASSIGN(InsideWith);
563 };
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000564
565 private:
566 Scope** const variable_;
567 Scope* const prev_;
568 const ScopeType type_;
569 int materialized_literal_count_;
570 int expected_properties_;
571 int with_nesting_count_;
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000572 LanguageMode language_mode_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000573 bool is_generator_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000574 };
575
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000576 // Report syntax error
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000577 void ReportUnexpectedToken(Token::Value token);
578 void ReportMessageAt(Scanner::Location location, const char* type) {
579 ReportMessageAt(location, type, NULL);
580 }
581 void ReportMessageAt(Scanner::Location location,
ricow@chromium.org55ee8072011-09-08 16:33:10 +0000582 const char* type,
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000583 const char* name_opt) {
ricow@chromium.org55ee8072011-09-08 16:33:10 +0000584 log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
585 }
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000586 void ReportMessageAt(int start_pos,
587 int end_pos,
588 const char* type,
589 const char* name_opt) {
590 log_->LogMessage(start_pos, end_pos, type, name_opt);
591 }
592
593 // All ParseXXX functions take as the last argument an *ok parameter
594 // which is set to false if parsing failed; it is unchanged otherwise.
595 // By making the 'exception handling' explicit, we are forced to check
596 // for failure at the call sites.
danno@chromium.orgb6451162011-08-17 14:33:23 +0000597 Statement ParseSourceElement(bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000598 SourceElements ParseSourceElements(int end_token, bool* ok);
599 Statement ParseStatement(bool* ok);
600 Statement ParseFunctionDeclaration(bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000601 Statement ParseBlock(bool* ok);
danno@chromium.orgb6451162011-08-17 14:33:23 +0000602 Statement ParseVariableStatement(VariableDeclarationContext var_context,
603 bool* ok);
604 Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000605 VariableDeclarationProperties* decl_props,
danno@chromium.orgb6451162011-08-17 14:33:23 +0000606 int* num_decl,
607 bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000608 Statement ParseExpressionOrLabelledStatement(bool* ok);
609 Statement ParseIfStatement(bool* ok);
610 Statement ParseContinueStatement(bool* ok);
611 Statement ParseBreakStatement(bool* ok);
612 Statement ParseReturnStatement(bool* ok);
613 Statement ParseWithStatement(bool* ok);
614 Statement ParseSwitchStatement(bool* ok);
615 Statement ParseDoWhileStatement(bool* ok);
616 Statement ParseWhileStatement(bool* ok);
617 Statement ParseForStatement(bool* ok);
618 Statement ParseThrowStatement(bool* ok);
619 Statement ParseTryStatement(bool* ok);
620 Statement ParseDebuggerStatement(bool* ok);
621
622 Expression ParseExpression(bool accept_IN, bool* ok);
623 Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000624 Expression ParseYieldExpression(bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000625 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
626 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
627 Expression ParseUnaryExpression(bool* ok);
628 Expression ParsePostfixExpression(bool* ok);
629 Expression ParseLeftHandSideExpression(bool* ok);
630 Expression ParseNewExpression(bool* ok);
631 Expression ParseMemberExpression(bool* ok);
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +0000632 Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000633 Expression ParsePrimaryExpression(bool* ok);
634 Expression ParseArrayLiteral(bool* ok);
635 Expression ParseObjectLiteral(bool* ok);
636 Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
637 Expression ParseV8Intrinsic(bool* ok);
638
639 Arguments ParseArguments(bool* ok);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000640 Expression ParseFunctionLiteral(bool is_generator, bool* ok);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000641 void ParseLazyFunctionLiteralBody(bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000642
643 Identifier ParseIdentifier(bool* ok);
644 Identifier ParseIdentifierName(bool* ok);
ager@chromium.org04921a82011-06-27 13:21:41 +0000645 Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
646 bool* is_set,
647 bool* ok);
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000648
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000649 // Logs the currently parsed literal as a symbol in the preparser data.
650 void LogSymbol();
651 // Log the currently parsed identifier.
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000652 Identifier GetIdentifierSymbol();
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000653 // Log the currently parsed string literal.
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000654 Expression GetStringSymbol();
655
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000656 void set_language_mode(LanguageMode language_mode) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000657 scope_->set_language_mode(language_mode);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000658 }
659
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000660 bool is_classic_mode() {
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000661 return scope_->language_mode() == CLASSIC_MODE;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000662 }
erik.corry@gmail.com6e28b562011-10-27 14:20:17 +0000663
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000664 bool is_extended_mode() {
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000665 return scope_->language_mode() == EXTENDED_MODE;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000666 }
667
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000668 LanguageMode language_mode() { return scope_->language_mode(); }
lrn@chromium.org1c092762011-05-09 09:42:16 +0000669
danno@chromium.org41728482013-06-12 22:31:22 +0000670 bool CheckInOrOf(bool accept_OF);
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000671
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000672 void SetStrictModeViolation(Scanner::Location,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000673 const char* type,
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000674 bool* ok);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000675
676 void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok);
677
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000678 void StrictModeIdentifierViolation(Scanner::Location,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000679 const char* eval_args_type,
680 Identifier identifier,
681 bool* ok);
682
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000683 ParserRecorder* log_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000684 Scope* scope_;
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +0000685 Scanner::Location strict_mode_violation_location_;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000686 const char* strict_mode_violation_type_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000687 bool parenthesized_function_;
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000688};
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000689
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000690} } // v8::internal
lrn@chromium.orgfa943b72010-11-03 08:14:36 +0000691
692#endif // V8_PREPARSER_H