Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: src/preparser.h

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/preparse-data-format.h ('k') | src/preparser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifndef V8_PREPARSER_H 28 #ifndef V8_PREPARSER_H
29 #define V8_PREPARSER_H 29 #define V8_PREPARSER_H
30 30
31 #include "hashmap.h" 31 #include "hashmap.h"
32 #include "lexer/experimental-scanner.h" 32 #include "scopes.h"
33 #include "token.h" 33 #include "token.h"
34 #include "scanner.h" 34 #include "scanner.h"
35 #include "lexer/lexer.h"
36 #include "v8.h"
35 37
36 namespace v8 { 38 namespace v8 {
37 namespace internal { 39 namespace internal {
38 40
39 // Common base class shared between parser and pre-parser. 41 // Common base class shared between parser and pre-parser.
40 class ParserBase { 42 template <typename Traits>
43 class ParserBase : public Traits {
41 public: 44 public:
42 ParserBase(ScannerBase* scanner, uintptr_t stack_limit) 45 ParserBase(Scanner* scanner, uintptr_t stack_limit,
43 : scanner_(scanner), 46 v8::Extension* extension,
44 allow_harmony_modules_(false), 47 typename Traits::Type::Zone* zone,
45 allow_harmony_scoping_(false), 48 typename Traits::Type::Parser this_object)
46 allow_harmony_numeric_literals_(false), 49 : Traits(this_object),
50 parenthesized_function_(false),
51 scope_(NULL),
52 function_state_(NULL),
53 extension_(extension),
54 scanner_(scanner),
47 stack_limit_(stack_limit), 55 stack_limit_(stack_limit),
48 stack_overflow_(false), 56 stack_overflow_(false),
49 allow_lazy_(false), 57 allow_lazy_(false),
50 allow_natives_syntax_(false), 58 allow_natives_syntax_(false),
51 allow_generators_(false), 59 allow_generators_(false),
52 allow_for_of_(false) { } 60 allow_for_of_(false),
53 // TODO(mstarzinger): Only virtual until message reporting has been unified. 61 zone_(zone) { }
54 // FIXME: Might need to continue to be virtual for the experimental branch.
55 virtual ~ParserBase() { }
56 62
57 // Getters that indicate whether certain syntactical constructs are 63 // Getters that indicate whether certain syntactical constructs are
58 // allowed to be parsed by this instance of the parser. 64 // allowed to be parsed by this instance of the parser.
59 bool allow_lazy() const { return allow_lazy_; } 65 bool allow_lazy() const { return allow_lazy_; }
60 bool allow_natives_syntax() const { return allow_natives_syntax_; } 66 bool allow_natives_syntax() const { return allow_natives_syntax_; }
61 bool allow_generators() const { return allow_generators_; } 67 bool allow_generators() const { return allow_generators_; }
62 bool allow_for_of() const { return allow_for_of_; } 68 bool allow_for_of() const { return allow_for_of_; }
63 bool allow_modules() const { return allow_harmony_modules_; } 69 bool allow_modules() const { return scanner()->HarmonyModules(); }
64 bool allow_harmony_scoping() const { return allow_harmony_scoping_; } 70 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
65 bool allow_harmony_numeric_literals() const { 71 bool allow_harmony_numeric_literals() const {
66 return allow_harmony_numeric_literals_; 72 return scanner()->HarmonyNumericLiterals();
67 } 73 }
68 74
69 // Setters that determine whether certain syntactical constructs are 75 // Setters that determine whether certain syntactical constructs are
70 // allowed to be parsed by this instance of the parser. 76 // allowed to be parsed by this instance of the parser.
71 void set_allow_lazy(bool allow) { allow_lazy_ = allow; } 77 void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
72 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; } 78 void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
73 void set_allow_generators(bool allow) { allow_generators_ = allow; } 79 void set_allow_generators(bool allow) { allow_generators_ = allow; }
74 void set_allow_for_of(bool allow) { allow_for_of_ = allow; } 80 void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
75 void set_allow_modules(bool allow) { 81 void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
76 allow_harmony_modules_ = allow;
77 if (scanner()) {
78 scanner()->SetHarmonyModules(allow);
79 }
80 }
81
82 void set_allow_harmony_scoping(bool allow) { 82 void set_allow_harmony_scoping(bool allow) {
83 allow_harmony_scoping_ = allow; 83 scanner()->SetHarmonyScoping(allow);
84 if (scanner()) {
85 scanner()->SetHarmonyScoping(allow);
86 }
87 } 84 }
88 void set_allow_harmony_numeric_literals(bool allow) { 85 void set_allow_harmony_numeric_literals(bool allow) {
89 allow_harmony_numeric_literals_ = allow; 86 scanner()->SetHarmonyNumericLiterals(allow);
90 if (scanner()) {
91 scanner()->SetHarmonyNumericLiterals(allow);
92 }
93 } 87 }
94 88
95 protected: 89 protected:
96 ScannerBase* scanner() const { return scanner_; } 90 enum AllowEvalOrArgumentsAsIdentifier {
91 kAllowEvalOrArguments,
92 kDontAllowEvalOrArguments
93 };
94
95 // ---------------------------------------------------------------------------
96 // FunctionState and BlockState together implement the parser's scope stack.
97 // The parser's current scope is in scope_. BlockState and FunctionState
98 // constructors push on the scope stack and the destructors pop. They are also
99 // used to hold the parser's per-function and per-block state.
100 class BlockState BASE_EMBEDDED {
101 public:
102 BlockState(typename Traits::Type::Scope** scope_stack,
103 typename Traits::Type::Scope* scope)
104 : scope_stack_(scope_stack),
105 outer_scope_(*scope_stack),
106 scope_(scope) {
107 *scope_stack_ = scope_;
108 }
109 ~BlockState() { *scope_stack_ = outer_scope_; }
110
111 private:
112 typename Traits::Type::Scope** scope_stack_;
113 typename Traits::Type::Scope* outer_scope_;
114 typename Traits::Type::Scope* scope_;
115 };
116
117 class FunctionState BASE_EMBEDDED {
118 public:
119 FunctionState(
120 FunctionState** function_state_stack,
121 typename Traits::Type::Scope** scope_stack,
122 typename Traits::Type::Scope* scope,
123 typename Traits::Type::Zone* zone = NULL);
124 ~FunctionState();
125
126 int NextMaterializedLiteralIndex() {
127 return next_materialized_literal_index_++;
128 }
129 int materialized_literal_count() {
130 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
131 }
132
133 int NextHandlerIndex() { return next_handler_index_++; }
134 int handler_count() { return next_handler_index_; }
135
136 void AddProperty() { expected_property_count_++; }
137 int expected_property_count() { return expected_property_count_; }
138
139 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
140 bool is_generator() const { return is_generator_; }
141
142 void set_generator_object_variable(
143 typename Traits::Type::GeneratorVariable* variable) {
144 ASSERT(variable != NULL);
145 ASSERT(!is_generator());
146 generator_object_variable_ = variable;
147 is_generator_ = true;
148 }
149 typename Traits::Type::GeneratorVariable* generator_object_variable()
150 const {
151 return generator_object_variable_;
152 }
153
154 typename Traits::Type::Factory* factory() { return &factory_; }
155
156 private:
157 // Used to assign an index to each literal that needs materialization in
158 // the function. Includes regexp literals, and boilerplate for object and
159 // array literals.
160 int next_materialized_literal_index_;
161
162 // Used to assign a per-function index to try and catch handlers.
163 int next_handler_index_;
164
165 // Properties count estimation.
166 int expected_property_count_;
167
168 // Whether the function is a generator.
169 bool is_generator_;
170 // For generators, this variable may hold the generator object. It variable
171 // is used by yield expressions and return statements. It is not necessary
172 // for generator functions to have this variable set.
173 Variable* generator_object_variable_;
174
175 FunctionState** function_state_stack_;
176 FunctionState* outer_function_state_;
177 typename Traits::Type::Scope** scope_stack_;
178 typename Traits::Type::Scope* outer_scope_;
179 Isolate* isolate_; // Only used by ParserTraits.
180 int saved_ast_node_id_; // Only used by ParserTraits.
181 typename Traits::Type::Factory factory_;
182
183 friend class ParserTraits;
184 };
185
186 Scanner* scanner() const { return scanner_; }
97 int position() { return scanner_->location().beg_pos; } 187 int position() { return scanner_->location().beg_pos; }
98 int peek_position() { return scanner_->peek_location().beg_pos; } 188 int peek_position() { return scanner_->peek_location().beg_pos; }
99 bool stack_overflow() const { return stack_overflow_; } 189 bool stack_overflow() const { return stack_overflow_; }
100 void set_stack_overflow() { stack_overflow_ = true; } 190 void set_stack_overflow() { stack_overflow_ = true; }
191 typename Traits::Type::Zone* zone() const { return zone_; }
101 192
102 INLINE(Token::Value peek()) { 193 INLINE(Token::Value peek()) {
103 if (stack_overflow_) return Token::ILLEGAL; 194 if (stack_overflow_) return Token::ILLEGAL;
104 return scanner()->peek(); 195 return scanner()->peek();
105 } 196 }
106 197
107 INLINE(Token::Value Next()) { 198 INLINE(Token::Value Next()) {
108 if (stack_overflow_) return Token::ILLEGAL; 199 if (stack_overflow_) return Token::ILLEGAL;
109 { 200 {
110 int marker; 201 int marker;
(...skipping 24 matching lines...) Expand all
135 } 226 }
136 227
137 void Expect(Token::Value token, bool* ok) { 228 void Expect(Token::Value token, bool* ok) {
138 Token::Value next = Next(); 229 Token::Value next = Next();
139 if (next != token) { 230 if (next != token) {
140 ReportUnexpectedToken(next); 231 ReportUnexpectedToken(next);
141 *ok = false; 232 *ok = false;
142 } 233 }
143 } 234 }
144 235
145 bool peek_any_identifier(); 236 void ExpectSemicolon(bool* ok) {
146 void ExpectSemicolon(bool* ok); 237 // Check for automatic semicolon insertion according to
147 bool CheckContextualKeyword(Vector<const char> keyword); 238 // the rules given in ECMA-262, section 7.9, page 21.
148 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok); 239 Token::Value tok = peek();
240 if (tok == Token::SEMICOLON) {
241 Next();
242 return;
243 }
244 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
245 tok == Token::RBRACE ||
246 tok == Token::EOS) {
247 return;
248 }
249 Expect(Token::SEMICOLON, ok);
250 }
149 251
150 // Strict mode octal literal validation. 252 bool peek_any_identifier() {
151 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok); 253 Token::Value next = peek();
254 return next == Token::IDENTIFIER ||
255 next == Token::FUTURE_RESERVED_WORD ||
256 next == Token::FUTURE_STRICT_RESERVED_WORD ||
257 next == Token::YIELD;
258 }
259
260 bool CheckContextualKeyword(Vector<const char> keyword) {
261 if (peek() == Token::IDENTIFIER &&
262 scanner()->is_next_contextual_keyword(keyword)) {
263 Consume(Token::IDENTIFIER);
264 return true;
265 }
266 return false;
267 }
268
269 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
270 Expect(Token::IDENTIFIER, ok);
271 if (!*ok) return;
272 if (!scanner()->is_literal_contextual_keyword(keyword)) {
273 ReportUnexpectedToken(scanner()->current_token());
274 *ok = false;
275 }
276 }
277
278 // Checks whether an octal literal was last seen between beg_pos and end_pos.
279 // If so, reports an error. Only called for strict mode.
280 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
281 Scanner::Location octal = scanner()->octal_position();
282 if (octal.IsValid() && beg_pos <= octal.beg_pos &&
283 octal.end_pos <= end_pos) {
284 ReportMessageAt(octal, "strict_octal_literal");
285 scanner()->clear_octal_position();
286 *ok = false;
287 }
288 }
152 289
153 // Determine precedence of given token. 290 // Determine precedence of given token.
154 static int Precedence(Token::Value token, bool accept_IN); 291 static int Precedence(Token::Value token, bool accept_IN) {
292 if (token == Token::IN && !accept_IN)
293 return 0; // 0 precedence will terminate binary expression parsing
294 return Token::Precedence(token);
295 }
296
297 typename Traits::Type::Factory* factory() {
298 return function_state_->factory();
299 }
300
301 bool is_classic_mode() const { return scope_->is_classic_mode(); }
302
303 bool is_generator() const { return function_state_->is_generator(); }
155 304
156 // Report syntax errors. 305 // Report syntax errors.
157 virtual void ReportUnexpectedToken(Token::Value token) = 0; 306 void ReportMessage(const char* message, Vector<const char*> args) {
158 virtual void ReportMessageAt(ScannerBase::Location loc, const char* type) = 0; 307 Scanner::Location source_location = scanner()->location();
308 Traits::ReportMessageAt(source_location, message, args);
309 }
310
311 void ReportMessageAt(Scanner::Location location, const char* message) {
312 Traits::ReportMessageAt(location, message, Vector<const char*>::empty());
313 }
314
315 void ReportUnexpectedToken(Token::Value token);
316
317 // Recursive descent functions:
318
319 // Parses an identifier that is valid for the current scope, in particular it
320 // fails on strict mode future reserved keywords in a strict scope. If
321 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
322 // "arguments" as identifier even in strict mode (this is needed in cases like
323 // "var foo = eval;").
324 typename Traits::Type::Identifier ParseIdentifier(
325 AllowEvalOrArgumentsAsIdentifier,
326 bool* ok);
327 // Parses an identifier or a strict mode future reserved word, and indicate
328 // whether it is strict mode future reserved.
329 typename Traits::Type::Identifier ParseIdentifierOrStrictReservedWord(
330 bool* is_strict_reserved,
331 bool* ok);
332 typename Traits::Type::Identifier ParseIdentifierName(bool* ok);
333 // Parses an identifier and determines whether or not it is 'get' or 'set'.
334 typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
335 bool* is_set,
336 bool* ok);
337
338 typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal,
339 bool* ok);
340
341 typename Traits::Type::Expression ParsePrimaryExpression(bool* ok);
342 typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok);
343 typename Traits::Type::Expression ParseArrayLiteral(bool* ok);
159 344
160 // Used to detect duplicates in object literals. Each of the values 345 // Used to detect duplicates in object literals. Each of the values
161 // kGetterProperty, kSetterProperty and kValueProperty represents 346 // kGetterProperty, kSetterProperty and kValueProperty represents
162 // a type of object literal property. When parsing a property, its 347 // a type of object literal property. When parsing a property, its
163 // type value is stored in the DuplicateFinder for the property name. 348 // type value is stored in the DuplicateFinder for the property name.
164 // Values are chosen so that having intersection bits means the there is 349 // Values are chosen so that having intersection bits means the there is
165 // an incompatibility. 350 // an incompatibility.
166 // I.e., you can add a getter to a property that already has a setter, since 351 // I.e., you can add a getter to a property that already has a setter, since
167 // kGetterProperty and kSetterProperty doesn't intersect, but not if it 352 // kGetterProperty and kSetterProperty doesn't intersect, but not if it
168 // already has a getter or a value. Adding the getter to an existing 353 // already has a getter or a value. Adding the getter to an existing
(...skipping 14 matching lines...) Expand all
183 public: 368 public:
184 ObjectLiteralChecker(ParserBase* parser, LanguageMode mode) 369 ObjectLiteralChecker(ParserBase* parser, LanguageMode mode)
185 : parser_(parser), 370 : parser_(parser),
186 finder_(scanner()->unicode_cache()), 371 finder_(scanner()->unicode_cache()),
187 language_mode_(mode) { } 372 language_mode_(mode) { }
188 373
189 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); 374 void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
190 375
191 private: 376 private:
192 ParserBase* parser() const { return parser_; } 377 ParserBase* parser() const { return parser_; }
193 ScannerBase* scanner() const { return parser_->scanner(); } 378 Scanner* scanner() const { return parser_->scanner(); }
194 379
195 // Checks the type of conflict based on values coming from PropertyType. 380 // Checks the type of conflict based on values coming from PropertyType.
196 bool HasConflict(PropertyKind type1, PropertyKind type2) { 381 bool HasConflict(PropertyKind type1, PropertyKind type2) {
197 return (type1 & type2) != 0; 382 return (type1 & type2) != 0;
198 } 383 }
199 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { 384 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
200 return ((type1 & type2) & kValueFlag) != 0; 385 return ((type1 & type2) & kValueFlag) != 0;
201 } 386 }
202 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { 387 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
203 return ((type1 ^ type2) & kValueFlag) != 0; 388 return ((type1 ^ type2) & kValueFlag) != 0;
204 } 389 }
205 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { 390 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
206 return ((type1 | type2) & kValueFlag) == 0; 391 return ((type1 | type2) & kValueFlag) == 0;
207 } 392 }
208 393
209 ParserBase* parser_; 394 ParserBase* parser_;
210 DuplicateFinder finder_; 395 DuplicateFinder finder_;
211 LanguageMode language_mode_; 396 LanguageMode language_mode_;
212 }; 397 };
213 398
214 ScannerBase* scanner_; 399 // If true, the next (and immediately following) function literal is
215 bool allow_harmony_modules_; 400 // preceded by a parenthesis.
216 bool allow_harmony_scoping_; 401 // Heuristically that means that the function will be called immediately,
217 bool allow_harmony_numeric_literals_; 402 // so never lazily compile it.
403 bool parenthesized_function_;
404
405 typename Traits::Type::Scope* scope_; // Scope stack.
406 FunctionState* function_state_; // Function state stack.
407 v8::Extension* extension_;
218 408
219 private: 409 private:
410 Scanner* scanner_;
220 uintptr_t stack_limit_; 411 uintptr_t stack_limit_;
221 bool stack_overflow_; 412 bool stack_overflow_;
222 413
223 bool allow_lazy_; 414 bool allow_lazy_;
224 bool allow_natives_syntax_; 415 bool allow_natives_syntax_;
225 bool allow_generators_; 416 bool allow_generators_;
226 bool allow_for_of_; 417 bool allow_for_of_;
227 }; 418
228 419 typename Traits::Type::Zone* zone_; // Only used by Parser.
229 420 };
421
422
423 class PreParserIdentifier {
424 public:
425 static PreParserIdentifier Default() {
426 return PreParserIdentifier(kUnknownIdentifier);
427 }
428 static PreParserIdentifier Eval() {
429 return PreParserIdentifier(kEvalIdentifier);
430 }
431 static PreParserIdentifier Arguments() {
432 return PreParserIdentifier(kArgumentsIdentifier);
433 }
434 static PreParserIdentifier FutureReserved() {
435 return PreParserIdentifier(kFutureReservedIdentifier);
436 }
437 static PreParserIdentifier FutureStrictReserved() {
438 return PreParserIdentifier(kFutureStrictReservedIdentifier);
439 }
440 static PreParserIdentifier Yield() {
441 return PreParserIdentifier(kYieldIdentifier);
442 }
443 bool IsEval() { return type_ == kEvalIdentifier; }
444 bool IsArguments() { return type_ == kArgumentsIdentifier; }
445 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
446 bool IsYield() { return type_ == kYieldIdentifier; }
447 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
448 bool IsFutureStrictReserved() {
449 return type_ == kFutureStrictReservedIdentifier;
450 }
451 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
452
453 private:
454 enum Type {
455 kUnknownIdentifier,
456 kFutureReservedIdentifier,
457 kFutureStrictReservedIdentifier,
458 kYieldIdentifier,
459 kEvalIdentifier,
460 kArgumentsIdentifier
461 };
462 explicit PreParserIdentifier(Type type) : type_(type) {}
463 Type type_;
464
465 friend class PreParserExpression;
466 };
467
468
469 // Bits 0 and 1 are used to identify the type of expression:
470 // If bit 0 is set, it's an identifier.
471 // if bit 1 is set, it's a string literal.
472 // If neither is set, it's no particular type, and both set isn't
473 // use yet.
474 class PreParserExpression {
475 public:
476 static PreParserExpression Default() {
477 return PreParserExpression(kUnknownExpression);
478 }
479
480 static PreParserExpression FromIdentifier(PreParserIdentifier id) {
481 return PreParserExpression(kIdentifierFlag |
482 (id.type_ << kIdentifierShift));
483 }
484
485 static PreParserExpression StringLiteral() {
486 return PreParserExpression(kUnknownStringLiteral);
487 }
488
489 static PreParserExpression UseStrictStringLiteral() {
490 return PreParserExpression(kUseStrictString);
491 }
492
493 static PreParserExpression This() {
494 return PreParserExpression(kThisExpression);
495 }
496
497 static PreParserExpression ThisProperty() {
498 return PreParserExpression(kThisPropertyExpression);
499 }
500
501 static PreParserExpression StrictFunction() {
502 return PreParserExpression(kStrictFunctionExpression);
503 }
504
505 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
506
507 // Only works corretly if it is actually an identifier expression.
508 PreParserIdentifier AsIdentifier() {
509 return PreParserIdentifier(
510 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
511 }
512
513 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
514
515 bool IsUseStrictLiteral() {
516 return (code_ & kStringLiteralMask) == kUseStrictString;
517 }
518
519 bool IsThis() { return code_ == kThisExpression; }
520
521 bool IsThisProperty() { return code_ == kThisPropertyExpression; }
522
523 bool IsStrictFunction() { return code_ == kStrictFunctionExpression; }
524
525 private:
526 // First two/three bits are used as flags.
527 // Bit 0 and 1 represent identifiers or strings literals, and are
528 // mutually exclusive, but can both be absent.
529 enum {
530 kUnknownExpression = 0,
531 // Identifiers
532 kIdentifierFlag = 1, // Used to detect labels.
533 kIdentifierShift = 3,
534
535 kStringLiteralFlag = 2, // Used to detect directive prologue.
536 kUnknownStringLiteral = kStringLiteralFlag,
537 kUseStrictString = kStringLiteralFlag | 8,
538 kStringLiteralMask = kUseStrictString,
539
540 // Below here applies if neither identifier nor string literal.
541 kThisExpression = 4,
542 kThisPropertyExpression = 8,
543 kStrictFunctionExpression = 12
544 };
545
546 explicit PreParserExpression(int expression_code) : code_(expression_code) {}
547
548 int code_;
549 };
550
551
552 // PreParserExpressionList doesn't actually store the expressions because
553 // PreParser doesn't need to.
554 class PreParserExpressionList {
555 public:
556 // These functions make list->Add(some_expression) work (and do nothing).
557 PreParserExpressionList* operator->() { return this; }
558 void Add(PreParserExpression, void*) { }
559 };
560
561
562 class PreParserScope {
563 public:
564 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type)
565 : scope_type_(scope_type) {
566 if (outer_scope) {
567 scope_inside_with_ =
568 outer_scope->scope_inside_with_ || is_with_scope();
569 language_mode_ = outer_scope->language_mode();
570 } else {
571 scope_inside_with_ = is_with_scope();
572 language_mode_ = CLASSIC_MODE;
573 }
574 }
575
576 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; }
577 bool is_classic_mode() const {
578 return language_mode() == CLASSIC_MODE;
579 }
580 bool is_extended_mode() {
581 return language_mode() == EXTENDED_MODE;
582 }
583 bool inside_with() const {
584 return scope_inside_with_;
585 }
586
587 ScopeType type() { return scope_type_; }
588 LanguageMode language_mode() const { return language_mode_; }
589 void SetLanguageMode(LanguageMode language_mode) {
590 language_mode_ = language_mode;
591 }
592
593 private:
594 ScopeType scope_type_;
595 bool scope_inside_with_;
596 LanguageMode language_mode_;
597 };
598
599
600 class PreParserFactory {
601 public:
602 explicit PreParserFactory(void* extra_param) {}
603
604 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
605 PreParserIdentifier js_flags,
606 int literal_index,
607 int pos) {
608 return PreParserExpression::Default();
609 }
610 PreParserExpression NewBinaryOperation(Token::Value op,
611 PreParserExpression left,
612 PreParserExpression right, int pos) {
613 return PreParserExpression::Default();
614 }
615 PreParserExpression NewArrayLiteral(PreParserExpressionList values,
616 int literal_index,
617 int pos) {
618 return PreParserExpression::Default();
619 }
620 };
621
622
623 class PreParser;
624
625 class PreParserTraits {
626 public:
627 struct Type {
628 typedef PreParser* Parser;
629
630 // Types used by FunctionState and BlockState.
631 typedef PreParserScope Scope;
632 typedef PreParserFactory Factory;
633 // PreParser doesn't need to store generator variables.
634 typedef void GeneratorVariable;
635 // No interaction with Zones.
636 typedef void Zone;
637
638 // Return types for traversing functions.
639 typedef PreParserIdentifier Identifier;
640 typedef PreParserExpression Expression;
641 typedef PreParserExpressionList ExpressionList;
642 };
643
644 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
645
646 // Custom operations executed when FunctionStates are created and
647 // destructed. (The PreParser doesn't need to do anything.)
648 template<typename FunctionState>
649 static void SetUpFunctionState(FunctionState* function_state, void*) {}
650 template<typename FunctionState>
651 static void TearDownFunctionState(FunctionState* function_state) {}
652
653 // Helper functions for recursive descent.
654 static bool IsEvalOrArguments(PreParserIdentifier identifier) {
655 return identifier.IsEvalOrArguments();
656 }
657
658 // Reporting errors.
659 void ReportMessageAt(Scanner::Location location,
660 const char* message,
661 Vector<const char*> args);
662 void ReportMessageAt(Scanner::Location location,
663 const char* type,
664 const char* name_opt);
665 void ReportMessageAt(int start_pos,
666 int end_pos,
667 const char* type,
668 const char* name_opt);
669
670 // "null" return type creators.
671 static PreParserIdentifier EmptyIdentifier() {
672 return PreParserIdentifier::Default();
673 }
674 static PreParserExpression EmptyExpression() {
675 return PreParserExpression::Default();
676 }
677
678 // Odd-ball literal creators.
679 static PreParserExpression GetLiteralTheHole(int position,
680 PreParserFactory* factory) {
681 return PreParserExpression::Default();
682 }
683
684 // Producing data during the recursive descent.
685 PreParserIdentifier GetSymbol(Scanner* scanner);
686 static PreParserIdentifier NextLiteralString(Scanner* scanner,
687 PretenureFlag tenured) {
688 return PreParserIdentifier::Default();
689 }
690
691 static PreParserExpression ThisExpression(PreParserScope* scope,
692 PreParserFactory* factory) {
693 return PreParserExpression::This();
694 }
695
696 static PreParserExpression ExpressionFromLiteral(
697 Token::Value token, int pos, Scanner* scanner,
698 PreParserFactory* factory) {
699 return PreParserExpression::Default();
700 }
701
702 static PreParserExpression ExpressionFromIdentifier(
703 PreParserIdentifier name, int pos, PreParserScope* scope,
704 PreParserFactory* factory) {
705 return PreParserExpression::FromIdentifier(name);
706 }
707
708 PreParserExpression ExpressionFromString(int pos,
709 Scanner* scanner,
710 PreParserFactory* factory = NULL);
711
712 static PreParserExpressionList NewExpressionList(int size, void* zone) {
713 return PreParserExpressionList();
714 }
715
716 // Temporary glue; these functions will move to ParserBase.
717 PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok);
718 PreParserExpression ParseObjectLiteral(bool* ok);
719 PreParserExpression ParseV8Intrinsic(bool* ok);
720
721 private:
722 PreParser* pre_parser_;
723 };
724
725
230 // Preparsing checks a JavaScript program and emits preparse-data that helps 726 // Preparsing checks a JavaScript program and emits preparse-data that helps
231 // a later parsing to be faster. 727 // a later parsing to be faster.
232 // See preparse-data-format.h for the data format. 728 // See preparse-data-format.h for the data format.
233 729
234 // The PreParser checks that the syntax follows the grammar for JavaScript, 730 // The PreParser checks that the syntax follows the grammar for JavaScript,
235 // and collects some information about the program along the way. 731 // and collects some information about the program along the way.
236 // The grammar check is only performed in order to understand the program 732 // The grammar check is only performed in order to understand the program
237 // sufficiently to deduce some information about it, that can be used 733 // sufficiently to deduce some information about it, that can be used
238 // to speed up later parsing. Finding errors is not the goal of pre-parsing, 734 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
239 // rather it is to speed up properly written and correct programs. 735 // rather it is to speed up properly written and correct programs.
240 // That means that contextual checks (like a label being declared where 736 // That means that contextual checks (like a label being declared where
241 // it is used) are generally omitted. 737 // it is used) are generally omitted.
242 class PreParser : public ParserBase { 738 class PreParser : public ParserBase<PreParserTraits> {
243 public: 739 public:
740 typedef PreParserIdentifier Identifier;
741 typedef PreParserExpression Expression;
742
244 enum PreParseResult { 743 enum PreParseResult {
245 kPreParseStackOverflow, 744 kPreParseStackOverflow,
246 kPreParseSuccess 745 kPreParseSuccess
247 }; 746 };
248 747
249 PreParser(ScannerBase* scanner, 748 PreParser(Scanner* scanner,
250 ParserRecorder* log, 749 ParserRecorder* log,
251 uintptr_t stack_limit) 750 uintptr_t stack_limit)
252 : ParserBase(scanner, stack_limit), 751 : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, NULL, this),
253 log_(log), 752 log_(log) {}
254 scope_(NULL),
255 strict_mode_violation_location_(ScannerBase::Location::invalid()),
256 strict_mode_violation_type_(NULL),
257 parenthesized_function_(false) { }
258
259 ~PreParser() {}
260 753
261 // Pre-parse the program from the character stream; returns true on 754 // Pre-parse the program from the character stream; returns true on
262 // success (even if parsing failed, the pre-parse data successfully 755 // success (even if parsing failed, the pre-parse data successfully
263 // captured the syntax error), and false if a stack-overflow happened 756 // captured the syntax error), and false if a stack-overflow happened
264 // during parsing. 757 // during parsing.
265 PreParseResult PreParseProgram() { 758 PreParseResult PreParseProgram() {
266 Scope top_scope(&scope_, kTopLevelScope); 759 PreParserScope scope(scope_, GLOBAL_SCOPE);
760 FunctionState top_scope(&function_state_, &scope_, &scope, NULL);
267 bool ok = true; 761 bool ok = true;
268 int start_position = scanner()->peek_location().beg_pos; 762 int start_position = scanner()->peek_location().beg_pos;
269 ParseSourceElements(Token::EOS, &ok); 763 ParseSourceElements(Token::EOS, &ok);
270 if (stack_overflow()) return kPreParseStackOverflow; 764 if (stack_overflow()) return kPreParseStackOverflow;
271 if (!ok) { 765 if (!ok) {
272 ReportUnexpectedToken(scanner()->current_token()); 766 ReportUnexpectedToken(scanner()->current_token());
273 } else if (!scope_->is_classic_mode()) { 767 } else if (!scope_->is_classic_mode()) {
274 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); 768 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
275 } 769 }
276 return kPreParseSuccess; 770 return kPreParseSuccess;
277 } 771 }
278 772
279 // Parses a single function literal, from the opening parentheses before 773 // Parses a single function literal, from the opening parentheses before
280 // parameters to the closing brace after the body. 774 // parameters to the closing brace after the body.
281 // Returns a FunctionEntry describing the body of the function in enough 775 // Returns a FunctionEntry describing the body of the function in enough
282 // detail that it can be lazily compiled. 776 // detail that it can be lazily compiled.
283 // The scanner is expected to have matched the "function" or "function*" 777 // The scanner is expected to have matched the "function" or "function*"
284 // keyword and parameters, and have consumed the initial '{'. 778 // keyword and parameters, and have consumed the initial '{'.
285 // At return, unless an error occurred, the scanner is positioned before the 779 // At return, unless an error occurred, the scanner is positioned before the
286 // the final '}'. 780 // the final '}'.
287 PreParseResult PreParseLazyFunction(LanguageMode mode, 781 PreParseResult PreParseLazyFunction(LanguageMode mode,
288 bool is_generator, 782 bool is_generator,
289 ParserRecorder* log); 783 ParserRecorder* log);
290 784
291 private: 785 private:
786 friend class PreParserTraits;
787
292 // These types form an algebra over syntactic categories that is just 788 // These types form an algebra over syntactic categories that is just
293 // rich enough to let us recognize and propagate the constructs that 789 // rich enough to let us recognize and propagate the constructs that
294 // are either being counted in the preparser data, or is important 790 // are either being counted in the preparser data, or is important
295 // to throw the correct syntax error exceptions. 791 // to throw the correct syntax error exceptions.
296 792
297 enum ScopeType {
298 kTopLevelScope,
299 kFunctionScope
300 };
301
302 enum VariableDeclarationContext { 793 enum VariableDeclarationContext {
303 kSourceElement, 794 kSourceElement,
304 kStatement, 795 kStatement,
305 kForStatement 796 kForStatement
306 }; 797 };
307 798
308 // If a list of variable declarations includes any initializers. 799 // If a list of variable declarations includes any initializers.
309 enum VariableDeclarationProperties { 800 enum VariableDeclarationProperties {
310 kHasInitializers, 801 kHasInitializers,
311 kHasNoInitializers 802 kHasNoInitializers
312 }; 803 };
313 804
314 class Expression;
315
316 class Identifier {
317 public:
318 static Identifier Default() {
319 return Identifier(kUnknownIdentifier);
320 }
321 static Identifier Eval() {
322 return Identifier(kEvalIdentifier);
323 }
324 static Identifier Arguments() {
325 return Identifier(kArgumentsIdentifier);
326 }
327 static Identifier FutureReserved() {
328 return Identifier(kFutureReservedIdentifier);
329 }
330 static Identifier FutureStrictReserved() {
331 return Identifier(kFutureStrictReservedIdentifier);
332 }
333 static Identifier Yield() {
334 return Identifier(kYieldIdentifier);
335 }
336 bool IsEval() { return type_ == kEvalIdentifier; }
337 bool IsArguments() { return type_ == kArgumentsIdentifier; }
338 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
339 bool IsYield() { return type_ == kYieldIdentifier; }
340 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
341 bool IsFutureStrictReserved() {
342 return type_ == kFutureStrictReservedIdentifier;
343 }
344 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
345
346 private:
347 enum Type {
348 kUnknownIdentifier,
349 kFutureReservedIdentifier,
350 kFutureStrictReservedIdentifier,
351 kYieldIdentifier,
352 kEvalIdentifier,
353 kArgumentsIdentifier
354 };
355 explicit Identifier(Type type) : type_(type) { }
356 Type type_;
357
358 friend class Expression;
359 };
360
361 // Bits 0 and 1 are used to identify the type of expression:
362 // If bit 0 is set, it's an identifier.
363 // if bit 1 is set, it's a string literal.
364 // If neither is set, it's no particular type, and both set isn't
365 // use yet.
366 // Bit 2 is used to mark the expression as being parenthesized,
367 // so "(foo)" isn't recognized as a pure identifier (and possible label).
368 class Expression {
369 public:
370 static Expression Default() {
371 return Expression(kUnknownExpression);
372 }
373
374 static Expression FromIdentifier(Identifier id) {
375 return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift));
376 }
377
378 static Expression StringLiteral() {
379 return Expression(kUnknownStringLiteral);
380 }
381
382 static Expression UseStrictStringLiteral() {
383 return Expression(kUseStrictString);
384 }
385
386 static Expression This() {
387 return Expression(kThisExpression);
388 }
389
390 static Expression ThisProperty() {
391 return Expression(kThisPropertyExpression);
392 }
393
394 static Expression StrictFunction() {
395 return Expression(kStrictFunctionExpression);
396 }
397
398 bool IsIdentifier() {
399 return (code_ & kIdentifierFlag) != 0;
400 }
401
402 // Only works corretly if it is actually an identifier expression.
403 PreParser::Identifier AsIdentifier() {
404 return PreParser::Identifier(
405 static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift));
406 }
407
408 bool IsParenthesized() {
409 // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized.
410 return (code_ & 7) > 4;
411 }
412
413 bool IsRawIdentifier() {
414 return !IsParenthesized() && IsIdentifier();
415 }
416
417 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
418
419 bool IsRawStringLiteral() {
420 return !IsParenthesized() && IsStringLiteral();
421 }
422
423 bool IsUseStrictLiteral() {
424 return (code_ & kStringLiteralMask) == kUseStrictString;
425 }
426
427 bool IsThis() {
428 return code_ == kThisExpression;
429 }
430
431 bool IsThisProperty() {
432 return code_ == kThisPropertyExpression;
433 }
434
435 bool IsStrictFunction() {
436 return code_ == kStrictFunctionExpression;
437 }
438
439 Expression Parenthesize() {
440 int type = code_ & 3;
441 if (type != 0) {
442 // Identifiers and string literals can be parenthesized.
443 // They no longer work as labels or directive prologues,
444 // but are still recognized in other contexts.
445 return Expression(code_ | kParenthesizedExpressionFlag);
446 }
447 // For other types of expressions, it's not important to remember
448 // the parentheses.
449 return *this;
450 }
451
452 private:
453 // First two/three bits are used as flags.
454 // Bit 0 and 1 represent identifiers or strings literals, and are
455 // mutually exclusive, but can both be absent.
456 // If bit 0 or 1 are set, bit 2 marks that the expression has
457 // been wrapped in parentheses (a string literal can no longer
458 // be a directive prologue, and an identifier can no longer be
459 // a label.
460 enum {
461 kUnknownExpression = 0,
462 // Identifiers
463 kIdentifierFlag = 1, // Used to detect labels.
464 kIdentifierShift = 3,
465
466 kStringLiteralFlag = 2, // Used to detect directive prologue.
467 kUnknownStringLiteral = kStringLiteralFlag,
468 kUseStrictString = kStringLiteralFlag | 8,
469 kStringLiteralMask = kUseStrictString,
470
471 // Only if identifier or string literal.
472 kParenthesizedExpressionFlag = 4,
473
474 // Below here applies if neither identifier nor string literal.
475 kThisExpression = 4,
476 kThisPropertyExpression = 8,
477 kStrictFunctionExpression = 12
478 };
479
480 explicit Expression(int expression_code) : code_(expression_code) { }
481
482 int code_;
483 };
484
485 class Statement { 805 class Statement {
486 public: 806 public:
487 static Statement Default() { 807 static Statement Default() {
488 return Statement(kUnknownStatement); 808 return Statement(kUnknownStatement);
489 } 809 }
490 810
491 static Statement FunctionDeclaration() { 811 static Statement FunctionDeclaration() {
492 return Statement(kFunctionDeclaration); 812 return Statement(kFunctionDeclaration);
493 } 813 }
494 814
495 // Creates expression statement from expression. 815 // Creates expression statement from expression.
496 // Preserves being an unparenthesized string literal, possibly 816 // Preserves being an unparenthesized string literal, possibly
497 // "use strict". 817 // "use strict".
498 static Statement ExpressionStatement(Expression expression) { 818 static Statement ExpressionStatement(Expression expression) {
499 if (!expression.IsParenthesized()) { 819 if (expression.IsUseStrictLiteral()) {
500 if (expression.IsUseStrictLiteral()) { 820 return Statement(kUseStrictExpressionStatement);
501 return Statement(kUseStrictExpressionStatement); 821 }
502 } 822 if (expression.IsStringLiteral()) {
503 if (expression.IsStringLiteral()) { 823 return Statement(kStringLiteralExpressionStatement);
504 return Statement(kStringLiteralExpressionStatement);
505 }
506 } 824 }
507 return Default(); 825 return Default();
508 } 826 }
509 827
510 bool IsStringLiteral() { 828 bool IsStringLiteral() {
511 return code_ == kStringLiteralExpressionStatement; 829 return code_ == kStringLiteralExpressionStatement;
512 } 830 }
513 831
514 bool IsUseStrictLiteral() { 832 bool IsUseStrictLiteral() {
515 return code_ == kUseStrictExpressionStatement; 833 return code_ == kUseStrictExpressionStatement;
(...skipping 14 matching lines...) Expand all
530 explicit Statement(Type code) : code_(code) {} 848 explicit Statement(Type code) : code_(code) {}
531 Type code_; 849 Type code_;
532 }; 850 };
533 851
534 enum SourceElements { 852 enum SourceElements {
535 kUnknownSourceElements 853 kUnknownSourceElements
536 }; 854 };
537 855
538 typedef int Arguments; 856 typedef int Arguments;
539 857
540 class Scope {
541 public:
542 Scope(Scope** variable, ScopeType type)
543 : variable_(variable),
544 prev_(*variable),
545 type_(type),
546 materialized_literal_count_(0),
547 expected_properties_(0),
548 with_nesting_count_(0),
549 language_mode_(
550 (prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE),
551 is_generator_(false) {
552 *variable = this;
553 }
554 ~Scope() { *variable_ = prev_; }
555 void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
556 void AddProperty() { expected_properties_++; }
557 ScopeType type() { return type_; }
558 int expected_properties() { return expected_properties_; }
559 int materialized_literal_count() { return materialized_literal_count_; }
560 bool IsInsideWith() { return with_nesting_count_ != 0; }
561 bool is_generator() { return is_generator_; }
562 void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
563 bool is_classic_mode() {
564 return language_mode_ == CLASSIC_MODE;
565 }
566 LanguageMode language_mode() {
567 return language_mode_;
568 }
569 void set_language_mode(LanguageMode language_mode) {
570 language_mode_ = language_mode;
571 }
572
573 class InsideWith {
574 public:
575 explicit InsideWith(Scope* scope) : scope_(scope) {
576 scope->with_nesting_count_++;
577 }
578
579 ~InsideWith() { scope_->with_nesting_count_--; }
580
581 private:
582 Scope* scope_;
583 DISALLOW_COPY_AND_ASSIGN(InsideWith);
584 };
585
586 private:
587 Scope** const variable_;
588 Scope* const prev_;
589 const ScopeType type_;
590 int materialized_literal_count_;
591 int expected_properties_;
592 int with_nesting_count_;
593 LanguageMode language_mode_;
594 bool is_generator_;
595 };
596
597 // Report syntax error
598 void ReportUnexpectedToken(Token::Value token);
599 void ReportMessageAt(ScannerBase::Location location, const char* type) {
600 ReportMessageAt(location, type, NULL);
601 }
602 void ReportMessageAt(ScannerBase::Location location,
603 const char* type,
604 const char* name_opt) {
605 log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
606 }
607 void ReportMessageAt(int start_pos,
608 int end_pos,
609 const char* type,
610 const char* name_opt) {
611 log_->LogMessage(start_pos, end_pos, type, name_opt);
612 }
613
614 // All ParseXXX functions take as the last argument an *ok parameter 858 // All ParseXXX functions take as the last argument an *ok parameter
615 // which is set to false if parsing failed; it is unchanged otherwise. 859 // which is set to false if parsing failed; it is unchanged otherwise.
616 // By making the 'exception handling' explicit, we are forced to check 860 // By making the 'exception handling' explicit, we are forced to check
617 // for failure at the call sites. 861 // for failure at the call sites.
618 Statement ParseSourceElement(bool* ok); 862 Statement ParseSourceElement(bool* ok);
619 SourceElements ParseSourceElements(int end_token, bool* ok); 863 SourceElements ParseSourceElements(int end_token, bool* ok);
620 Statement ParseStatement(bool* ok); 864 Statement ParseStatement(bool* ok);
621 Statement ParseFunctionDeclaration(bool* ok); 865 Statement ParseFunctionDeclaration(bool* ok);
622 Statement ParseBlock(bool* ok); 866 Statement ParseBlock(bool* ok);
623 Statement ParseVariableStatement(VariableDeclarationContext var_context, 867 Statement ParseVariableStatement(VariableDeclarationContext var_context,
624 bool* ok); 868 bool* ok);
625 Statement ParseVariableDeclarations(VariableDeclarationContext var_context, 869 Statement ParseVariableDeclarations(VariableDeclarationContext var_context,
626 VariableDeclarationProperties* decl_props, 870 VariableDeclarationProperties* decl_props,
627 int* num_decl, 871 int* num_decl,
628 bool* ok); 872 bool* ok);
629 Statement ParseExpressionOrLabelledStatement(bool* ok); 873 Statement ParseExpressionOrLabelledStatement(bool* ok);
630 Statement ParseIfStatement(bool* ok); 874 Statement ParseIfStatement(bool* ok);
631 Statement ParseContinueStatement(bool* ok); 875 Statement ParseContinueStatement(bool* ok);
632 Statement ParseBreakStatement(bool* ok); 876 Statement ParseBreakStatement(bool* ok);
633 Statement ParseReturnStatement(bool* ok); 877 Statement ParseReturnStatement(bool* ok);
634 Statement ParseWithStatement(bool* ok); 878 Statement ParseWithStatement(bool* ok);
635 Statement ParseSwitchStatement(bool* ok); 879 Statement ParseSwitchStatement(bool* ok);
636 Statement ParseDoWhileStatement(bool* ok); 880 Statement ParseDoWhileStatement(bool* ok);
637 Statement ParseWhileStatement(bool* ok); 881 Statement ParseWhileStatement(bool* ok);
638 Statement ParseForStatement(bool* ok); 882 Statement ParseForStatement(bool* ok);
639 Statement ParseThrowStatement(bool* ok); 883 Statement ParseThrowStatement(bool* ok);
640 Statement ParseTryStatement(bool* ok); 884 Statement ParseTryStatement(bool* ok);
641 Statement ParseDebuggerStatement(bool* ok); 885 Statement ParseDebuggerStatement(bool* ok);
642 886
643 Expression ParseExpression(bool accept_IN, bool* ok);
644 Expression ParseAssignmentExpression(bool accept_IN, bool* ok); 887 Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
645 Expression ParseYieldExpression(bool* ok); 888 Expression ParseYieldExpression(bool* ok);
646 Expression ParseConditionalExpression(bool accept_IN, bool* ok); 889 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
647 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); 890 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
648 Expression ParseUnaryExpression(bool* ok); 891 Expression ParseUnaryExpression(bool* ok);
649 Expression ParsePostfixExpression(bool* ok); 892 Expression ParsePostfixExpression(bool* ok);
650 Expression ParseLeftHandSideExpression(bool* ok); 893 Expression ParseLeftHandSideExpression(bool* ok);
651 Expression ParseNewExpression(bool* ok);
652 Expression ParseMemberExpression(bool* ok); 894 Expression ParseMemberExpression(bool* ok);
653 Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok); 895 Expression ParseMemberExpressionContinuation(PreParserExpression expression,
654 Expression ParsePrimaryExpression(bool* ok); 896 bool* ok);
655 Expression ParseArrayLiteral(bool* ok); 897 Expression ParseMemberWithNewPrefixesExpression(bool* ok);
656 Expression ParseObjectLiteral(bool* ok); 898 Expression ParseObjectLiteral(bool* ok);
657 Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
658 Expression ParseV8Intrinsic(bool* ok); 899 Expression ParseV8Intrinsic(bool* ok);
659 900
660 Arguments ParseArguments(bool* ok); 901 Arguments ParseArguments(bool* ok);
661 Expression ParseFunctionLiteral(bool is_generator, bool* ok); 902 Expression ParseFunctionLiteral(
903 Identifier name,
904 Scanner::Location function_name_location,
905 bool name_is_strict_reserved,
906 bool is_generator,
907 bool* ok);
662 void ParseLazyFunctionLiteralBody(bool* ok); 908 void ParseLazyFunctionLiteralBody(bool* ok);
663 909
664 Identifier ParseIdentifier(bool* ok);
665 Identifier ParseIdentifierName(bool* ok);
666 Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
667 bool* is_set,
668 bool* ok);
669
670 // Logs the currently parsed literal as a symbol in the preparser data. 910 // Logs the currently parsed literal as a symbol in the preparser data.
671 void LogSymbol(); 911 void LogSymbol();
672 // Log the currently parsed identifier.
673 Identifier GetIdentifierSymbol();
674 // Log the currently parsed string literal. 912 // Log the currently parsed string literal.
675 Expression GetStringSymbol(); 913 Expression GetStringSymbol();
676 914
677 void set_language_mode(LanguageMode language_mode) {
678 scope_->set_language_mode(language_mode);
679 }
680
681 bool is_classic_mode() {
682 return scope_->language_mode() == CLASSIC_MODE;
683 }
684
685 bool is_extended_mode() {
686 return scope_->language_mode() == EXTENDED_MODE;
687 }
688
689 LanguageMode language_mode() { return scope_->language_mode(); }
690
691 bool CheckInOrOf(bool accept_OF); 915 bool CheckInOrOf(bool accept_OF);
692 916
693 void SetStrictModeViolation(ScannerBase::Location,
694 const char* type,
695 bool* ok);
696
697 void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok);
698
699 void StrictModeIdentifierViolation(ScannerBase::Location,
700 const char* eval_args_type,
701 Identifier identifier,
702 bool* ok);
703
704 ParserRecorder* log_; 917 ParserRecorder* log_;
705 Scope* scope_;
706 ScannerBase::Location strict_mode_violation_location_;
707 const char* strict_mode_violation_type_;
708 bool parenthesized_function_;
709 }; 918 };
710 919
920
921 template<class Traits>
922 ParserBase<Traits>::FunctionState::FunctionState(
923 FunctionState** function_state_stack,
924 typename Traits::Type::Scope** scope_stack,
925 typename Traits::Type::Scope* scope,
926 typename Traits::Type::Zone* extra_param)
927 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
928 next_handler_index_(0),
929 expected_property_count_(0),
930 is_generator_(false),
931 generator_object_variable_(NULL),
932 function_state_stack_(function_state_stack),
933 outer_function_state_(*function_state_stack),
934 scope_stack_(scope_stack),
935 outer_scope_(*scope_stack),
936 isolate_(NULL),
937 saved_ast_node_id_(0),
938 factory_(extra_param) {
939 *scope_stack_ = scope;
940 *function_state_stack = this;
941 Traits::SetUpFunctionState(this, extra_param);
942 }
943
944
945 template<class Traits>
946 ParserBase<Traits>::FunctionState::~FunctionState() {
947 *scope_stack_ = outer_scope_;
948 *function_state_stack_ = outer_function_state_;
949 Traits::TearDownFunctionState(this);
950 }
951
952
953 template<class Traits>
954 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
955 // We don't report stack overflows here, to avoid increasing the
956 // stack depth even further. Instead we report it after parsing is
957 // over, in ParseProgram.
958 if (token == Token::ILLEGAL && stack_overflow()) {
959 return;
960 }
961 Scanner::Location source_location = scanner()->location();
962
963 // Four of the tokens are treated specially
964 switch (token) {
965 case Token::EOS:
966 return ReportMessageAt(source_location, "unexpected_eos");
967 case Token::NUMBER:
968 return ReportMessageAt(source_location, "unexpected_token_number");
969 case Token::STRING:
970 return ReportMessageAt(source_location, "unexpected_token_string");
971 case Token::IDENTIFIER:
972 return ReportMessageAt(source_location, "unexpected_token_identifier");
973 case Token::FUTURE_RESERVED_WORD:
974 return ReportMessageAt(source_location, "unexpected_reserved");
975 case Token::YIELD:
976 case Token::FUTURE_STRICT_RESERVED_WORD:
977 return ReportMessageAt(source_location,
978 is_classic_mode() ? "unexpected_token_identifier"
979 : "unexpected_strict_reserved");
980 default:
981 const char* name = Token::String(token);
982 ASSERT(name != NULL);
983 Traits::ReportMessageAt(
984 source_location, "unexpected_token", Vector<const char*>(&name, 1));
985 }
986 }
987
988
989 template<class Traits>
990 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier(
991 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
992 bool* ok) {
993 Token::Value next = Next();
994 if (next == Token::IDENTIFIER) {
995 typename Traits::Type::Identifier name = this->GetSymbol(scanner());
996 if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
997 !is_classic_mode() && this->IsEvalOrArguments(name)) {
998 ReportMessageAt(scanner()->location(), "strict_eval_arguments");
999 *ok = false;
1000 }
1001 return name;
1002 } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1003 (next == Token::YIELD && !is_generator()))) {
1004 return this->GetSymbol(scanner());
1005 } else {
1006 this->ReportUnexpectedToken(next);
1007 *ok = false;
1008 return Traits::EmptyIdentifier();
1009 }
1010 }
1011
1012
1013 template <class Traits>
1014 typename Traits::Type::Identifier ParserBase<
1015 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
1016 bool* ok) {
1017 Token::Value next = Next();
1018 if (next == Token::IDENTIFIER) {
1019 *is_strict_reserved = false;
1020 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
1021 (next == Token::YIELD && !this->is_generator())) {
1022 *is_strict_reserved = true;
1023 } else {
1024 ReportUnexpectedToken(next);
1025 *ok = false;
1026 return Traits::EmptyIdentifier();
1027 }
1028 return this->GetSymbol(scanner());
1029 }
1030
1031
1032 template <class Traits>
1033 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName(
1034 bool* ok) {
1035 Token::Value next = Next();
1036 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
1037 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
1038 this->ReportUnexpectedToken(next);
1039 *ok = false;
1040 return Traits::EmptyIdentifier();
1041 }
1042 return this->GetSymbol(scanner());
1043 }
1044
1045
1046 template <class Traits>
1047 typename Traits::Type::Identifier
1048 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
1049 bool* is_set,
1050 bool* ok) {
1051 typename Traits::Type::Identifier result = ParseIdentifierName(ok);
1052 if (!*ok) return Traits::EmptyIdentifier();
1053 if (scanner()->is_literal_ascii() &&
1054 scanner()->literal_length() == 3) {
1055 const char* token = scanner()->literal_ascii_string().start();
1056 *is_get = strncmp(token, "get", 3) == 0;
1057 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1058 }
1059 return result;
1060 }
1061
1062
1063 template <class Traits>
1064 typename Traits::Type::Expression
1065 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
1066 int pos = peek_position();
1067 if (!scanner()->ScanRegExpPattern(seen_equal)) {
1068 Next();
1069 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
1070 *ok = false;
1071 return Traits::EmptyExpression();
1072 }
1073
1074 int literal_index = function_state_->NextMaterializedLiteralIndex();
1075
1076 typename Traits::Type::Identifier js_pattern =
1077 this->NextLiteralString(scanner(), TENURED);
1078 if (!scanner()->ScanRegExpFlags()) {
1079 Next();
1080 ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
1081 *ok = false;
1082 return Traits::EmptyExpression();
1083 }
1084 typename Traits::Type::Identifier js_flags =
1085 this->NextLiteralString(scanner(), TENURED);
1086 Next();
1087 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
1088 }
1089
1090
1091 #define CHECK_OK ok); \
1092 if (!*ok) return this->EmptyExpression(); \
1093 ((void)0
1094 #define DUMMY ) // to make indentation work
1095 #undef DUMMY
1096
1097 template <class Traits>
1098 typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression(
1099 bool* ok) {
1100 // PrimaryExpression ::
1101 // 'this'
1102 // 'null'
1103 // 'true'
1104 // 'false'
1105 // Identifier
1106 // Number
1107 // String
1108 // ArrayLiteral
1109 // ObjectLiteral
1110 // RegExpLiteral
1111 // '(' Expression ')'
1112
1113 int pos = peek_position();
1114 typename Traits::Type::Expression result = this->EmptyExpression();
1115 Token::Value token = peek();
1116 switch (token) {
1117 case Token::THIS: {
1118 Consume(Token::THIS);
1119 result = this->ThisExpression(scope_, factory());
1120 break;
1121 }
1122
1123 case Token::NULL_LITERAL:
1124 case Token::TRUE_LITERAL:
1125 case Token::FALSE_LITERAL:
1126 case Token::NUMBER:
1127 Next();
1128 result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
1129 break;
1130
1131 case Token::IDENTIFIER:
1132 case Token::YIELD:
1133 case Token::FUTURE_STRICT_RESERVED_WORD: {
1134 // Using eval or arguments in this context is OK even in strict mode.
1135 typename Traits::Type::Identifier name =
1136 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1137 result =
1138 this->ExpressionFromIdentifier(name, pos, scope_, factory());
1139 break;
1140 }
1141
1142 case Token::STRING: {
1143 Consume(Token::STRING);
1144 result = this->ExpressionFromString(pos, scanner(), factory());
1145 break;
1146 }
1147
1148 case Token::ASSIGN_DIV:
1149 result = this->ParseRegExpLiteral(true, CHECK_OK);
1150 break;
1151
1152 case Token::DIV:
1153 result = this->ParseRegExpLiteral(false, CHECK_OK);
1154 break;
1155
1156 case Token::LBRACK:
1157 result = this->ParseArrayLiteral(CHECK_OK);
1158 break;
1159
1160 case Token::LBRACE:
1161 result = this->ParseObjectLiteral(CHECK_OK);
1162 break;
1163
1164 case Token::LPAREN:
1165 Consume(Token::LPAREN);
1166 // Heuristically try to detect immediately called functions before
1167 // seeing the call parentheses.
1168 parenthesized_function_ = (peek() == Token::FUNCTION);
1169 result = this->ParseExpression(true, CHECK_OK);
1170 Expect(Token::RPAREN, CHECK_OK);
1171 break;
1172
1173 case Token::MOD:
1174 if (allow_natives_syntax() || extension_ != NULL) {
1175 result = this->ParseV8Intrinsic(CHECK_OK);
1176 break;
1177 }
1178 // If we're not allowing special syntax we fall-through to the
1179 // default case.
1180
1181 default: {
1182 Next();
1183 ReportUnexpectedToken(token);
1184 *ok = false;
1185 }
1186 }
1187
1188 return result;
1189 }
1190
1191 // Precedence = 1
1192 template <class Traits>
1193 typename Traits::Type::Expression ParserBase<Traits>::ParseExpression(
1194 bool accept_IN, bool* ok) {
1195 // Expression ::
1196 // AssignmentExpression
1197 // Expression ',' AssignmentExpression
1198
1199 typename Traits::Type::Expression result =
1200 this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1201 while (peek() == Token::COMMA) {
1202 Expect(Token::COMMA, CHECK_OK);
1203 int pos = position();
1204 typename Traits::Type::Expression right =
1205 this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1206 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
1207 }
1208 return result;
1209 }
1210
1211
1212 template <class Traits>
1213 typename Traits::Type::Expression ParserBase<Traits>::ParseArrayLiteral(
1214 bool* ok) {
1215 // ArrayLiteral ::
1216 // '[' Expression? (',' Expression?)* ']'
1217
1218 int pos = peek_position();
1219 typename Traits::Type::ExpressionList values =
1220 this->NewExpressionList(4, zone_);
1221 Expect(Token::LBRACK, CHECK_OK);
1222 while (peek() != Token::RBRACK) {
1223 typename Traits::Type::Expression elem = this->EmptyExpression();
1224 if (peek() == Token::COMMA) {
1225 elem = this->GetLiteralTheHole(peek_position(), factory());
1226 } else {
1227 elem = this->ParseAssignmentExpression(true, CHECK_OK);
1228 }
1229 values->Add(elem, zone_);
1230 if (peek() != Token::RBRACK) {
1231 Expect(Token::COMMA, CHECK_OK);
1232 }
1233 }
1234 Expect(Token::RBRACK, CHECK_OK);
1235
1236 // Update the scope information before the pre-parsing bailout.
1237 int literal_index = function_state_->NextMaterializedLiteralIndex();
1238
1239 return factory()->NewArrayLiteral(values, literal_index, pos);
1240 }
1241
1242 #undef CHECK_OK
1243
1244
1245 template <typename Traits>
1246 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
1247 Token::Value property,
1248 PropertyKind type,
1249 bool* ok) {
1250 int old;
1251 if (property == Token::NUMBER) {
1252 old = finder_.AddNumber(scanner()->literal_ascii_string(), type);
1253 } else if (scanner()->is_literal_ascii()) {
1254 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type);
1255 } else {
1256 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type);
1257 }
1258 PropertyKind old_type = static_cast<PropertyKind>(old);
1259 if (HasConflict(old_type, type)) {
1260 if (IsDataDataConflict(old_type, type)) {
1261 // Both are data properties.
1262 if (language_mode_ == CLASSIC_MODE) return;
1263 parser()->ReportMessageAt(scanner()->location(),
1264 "strict_duplicate_property");
1265 } else if (IsDataAccessorConflict(old_type, type)) {
1266 // Both a data and an accessor property with the same name.
1267 parser()->ReportMessageAt(scanner()->location(),
1268 "accessor_data_property");
1269 } else {
1270 ASSERT(IsAccessorAccessorConflict(old_type, type));
1271 // Both accessors of the same type.
1272 parser()->ReportMessageAt(scanner()->location(),
1273 "accessor_get_set");
1274 }
1275 *ok = false;
1276 }
1277 }
1278
1279
711 } } // v8::internal 1280 } } // v8::internal
712 1281
713 #endif // V8_PREPARSER_H 1282 #endif // V8_PREPARSER_H
OLDNEW
« no previous file with comments | « src/preparse-data-format.h ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698