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

Side by Side Diff: src/preparser.h

Issue 4112012: Stand-alone parser template. (Closed)
Patch Set: Addressed review comments. Created 10 years, 1 month 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
« no previous file with comments | « src/parser.cc ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // 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
31 #include "unicode.h"
32
33 namespace v8 {
34 namespace internal {
35 namespace preparser {
36
37 // Preparsing checks a JavaScript program and emits preparse-data that helps
38 // a later parsing to be faster.
39 // See preparser-data.h for the data.
40
41 // The PreParser checks that the syntax follows the grammar for JavaScript,
42 // and collects some information about the program along the way.
43 // The grammar check is only performed in order to understand the program
44 // sufficiently to deduce some information about it, that can be used
45 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
46 // rather it is to speed up properly written and correct programs.
47 // That means that contextual checks (like a label being declared where
48 // it is used) are generally omitted.
49
50 enum StatementType {
51 kUnknownStatement
52 };
53
54 enum ExpressionType {
55 kUnknownExpression,
56 kIdentifierExpression, // Used to detect labels.
57 kThisExpression,
58 kThisPropertyExpression
59 };
60
61 enum IdentifierType {
62 kUnknownIdentifier
63 };
64
65 enum SourceElementTypes {
66 kUnknownSourceElements
67 };
68
69
70 typedef int SourceElements;
71 typedef int Expression;
72 typedef int Statement;
73 typedef int Identifier;
74 typedef int Arguments;
75
76
77 template <typename Scanner, typename PreParserLog>
78 class PreParser {
79 public:
80 PreParser() : scope_(NULL), allow_lazy_(true) { }
81 ~PreParser() { }
82
83 // Pre-parse the program from the character stream; returns true on
84 // success (even if parsing failed, the pre-parse data successfully
85 // captured the syntax error), and false if a stack-overflow happened
86 // during parsing.
87 bool PreParseProgram(Scanner* scanner,
88 PreParserLog* log,
89 bool allow_lazy) {
90 allow_lazy_ = allow_lazy;
91 scanner_ = scanner;
92 log_ = log;
93 Scope top_scope(&scope_, kTopLevelScope);
94 bool ok = true;
95 ParseSourceElements(Token::EOS, &ok);
96 bool stack_overflow = scanner_->stack_overflow();
97 if (!ok && !stack_overflow) {
98 ReportUnexpectedToken(scanner_->current_token());
99 }
100 return !stack_overflow;
101 }
102
103 private:
104 enum ScopeType {
105 kTopLevelScope,
106 kFunctionScope
107 };
108
109 class Scope {
110 public:
111 Scope(Scope** variable, ScopeType type)
112 : variable_(variable),
113 prev_(*variable),
114 type_(type),
115 materialized_literal_count_(0),
116 expected_properties_(0),
117 with_nesting_count_(0) {
118 *variable = this;
119 }
120 ~Scope() { *variable_ = prev_; }
121 void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
122 void AddProperty() { expected_properties_++; }
123 ScopeType type() { return type_; }
124 int expected_properties() { return expected_properties_; }
125 int materialized_literal_count() { return materialized_literal_count_; }
126 bool IsInsideWith() { return with_nesting_count_ != 0; }
127 void EnterWith() { with_nesting_count_++; }
128 void LeaveWith() { with_nesting_count_--; }
129
130 private:
131 Scope** const variable_;
132 Scope* const prev_;
133 const ScopeType type_;
134 int materialized_literal_count_;
135 int expected_properties_;
136 int with_nesting_count_;
137 };
138
139 // Types that allow us to recognize simple this-property assignments.
140 // A simple this-property assignment is a statement on the form
141 // "this.propertyName = {primitive constant or function parameter name);"
142 // where propertyName isn't "__proto__".
143 // The result is only relevant if the function body contains only
144 // simple this-property assignments.
145
146 // Report syntax error
147 void ReportUnexpectedToken(Token::Value token);
148 void ReportMessageAt(int start_pos,
149 int end_pos,
150 const char* type,
151 const char* name_opt) {
152 log_->LogMessage(start_pos, end_pos, type, name_opt);
153 }
154
155 // All ParseXXX functions take as the last argument an *ok parameter
156 // which is set to false if parsing failed; it is unchanged otherwise.
157 // By making the 'exception handling' explicit, we are forced to check
158 // for failure at the call sites.
159 SourceElements ParseSourceElements(int end_token, bool* ok);
160 Statement ParseStatement(bool* ok);
161 Statement ParseFunctionDeclaration(bool* ok);
162 Statement ParseNativeDeclaration(bool* ok);
163 Statement ParseBlock(bool* ok);
164 Statement ParseVariableStatement(bool* ok);
165 Statement ParseVariableDeclarations(bool accept_IN, int* num_decl, bool* ok);
166 Statement ParseExpressionOrLabelledStatement(bool* ok);
167 Statement ParseIfStatement(bool* ok);
168 Statement ParseContinueStatement(bool* ok);
169 Statement ParseBreakStatement(bool* ok);
170 Statement ParseReturnStatement(bool* ok);
171 Statement ParseWithStatement(bool* ok);
172 Statement ParseSwitchStatement(bool* ok);
173 Statement ParseDoWhileStatement(bool* ok);
174 Statement ParseWhileStatement(bool* ok);
175 Statement ParseForStatement(bool* ok);
176 Statement ParseThrowStatement(bool* ok);
177 Statement ParseTryStatement(bool* ok);
178 Statement ParseDebuggerStatement(bool* ok);
179
180 Expression ParseExpression(bool accept_IN, bool* ok);
181 Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
182 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
183 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
184 Expression ParseUnaryExpression(bool* ok);
185 Expression ParsePostfixExpression(bool* ok);
186 Expression ParseLeftHandSideExpression(bool* ok);
187 Expression ParseNewExpression(bool* ok);
188 Expression ParseMemberExpression(bool* ok);
189 Expression ParseNewPrefix(int* new_count, bool* ok);
190 Expression ParseMemberWithNewPrefixesExpression(int* new_count, bool* ok);
191 Expression ParsePrimaryExpression(bool* ok);
192 Expression ParseArrayLiteral(bool* ok);
193 Expression ParseObjectLiteral(bool* ok);
194 Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
195 Expression ParseV8Intrinsic(bool* ok);
196
197 Arguments ParseArguments(bool* ok);
198 Expression ParseFunctionLiteral(bool* ok);
199
200 Identifier ParseIdentifier(bool* ok);
201 Identifier ParseIdentifierName(bool* ok);
202 Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok);
203
204 Identifier GetIdentifierSymbol();
205 unsigned int HexDigitValue(char digit);
206 Expression GetStringSymbol();
207
208
209 Token::Value peek() { return scanner_->peek(); }
210 Token::Value Next() {
211 Token::Value next = scanner_->Next();
212 return next;
213 }
214
215 void Consume(Token::Value token) {
216 Next();
217 }
218
219 void Expect(Token::Value token, bool* ok) {
220 if (Next() != token) {
221 *ok = false;
222 }
223 }
224
225 bool Check(Token::Value token) {
226 Token::Value next = peek();
227 if (next == token) {
228 Consume(next);
229 return true;
230 }
231 return false;
232 }
233 void ExpectSemicolon(bool* ok);
234
235 static int Precedence(Token::Value tok, bool accept_IN);
236
237 Scanner* scanner_;
238 PreParserLog* log_;
239 Scope* scope_;
240 bool allow_lazy_;
241 };
242
243
244 #define CHECK_OK ok); \
245 if (!*ok) return -1; \
Mads Ager (chromium) 2010/11/02 07:17:03 Align the two '\'
246 ((void)0
247 #define DUMMY ) // to make indentation work
248 #undef DUMMY
249
250
251 template <typename Scanner, typename Log>
252 void PreParser<Scanner, Log>::ReportUnexpectedToken(Token::Value token) {
253 // We don't report stack overflows here, to avoid increasing the
254 // stack depth even further. Instead we report it after parsing is
255 // over, in ParseProgram.
256 if (token == Token::ILLEGAL && scanner_->stack_overflow()) {
257 return;
258 }
259 typename Scanner::Location source_location = scanner_->location();
260
261 // Four of the tokens are treated specially
262 switch (token) {
263 case Token::EOS:
264 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
265 "unexpected_eos", NULL);
266 case Token::NUMBER:
267 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
268 "unexpected_token_number", NULL);
269 case Token::STRING:
270 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
271 "unexpected_token_string", NULL);
272 case Token::IDENTIFIER:
273 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
274 "unexpected_token_identifier", NULL);
275 default:
276 const char* name = Token::String(token);
277 ReportMessageAt(source_location.beg_pos, source_location.end_pos,
278 "unexpected_token", name);
279 }
280 }
281
282
283 template <typename Scanner, typename Log>
284 SourceElements PreParser<Scanner, Log>::ParseSourceElements(int end_token,
285 bool* ok) {
286 // SourceElements ::
287 // (Statement)* <end_token>
288
289 while (peek() != end_token) {
290 ParseStatement(CHECK_OK);
291 }
292 return kUnknownSourceElements;
293 }
294
295
296 template <typename Scanner, typename Log>
297 Statement PreParser<Scanner, Log>::ParseStatement(bool* ok) {
298 // Statement ::
299 // Block
300 // VariableStatement
301 // EmptyStatement
302 // ExpressionStatement
303 // IfStatement
304 // IterationStatement
305 // ContinueStatement
306 // BreakStatement
307 // ReturnStatement
308 // WithStatement
309 // LabelledStatement
310 // SwitchStatement
311 // ThrowStatement
312 // TryStatement
313 // DebuggerStatement
314
315 // Note: Since labels can only be used by 'break' and 'continue'
316 // statements, which themselves are only valid within blocks,
317 // iterations or 'switch' statements (i.e., BreakableStatements),
318 // labels can be simply ignored in all other cases; except for
319 // trivial labeled break statements 'label: break label' which is
320 // parsed into an empty statement.
321
322 // Keep the source position of the statement
323 switch (peek()) {
324 case Token::LBRACE:
325 return ParseBlock(ok);
326
327 case Token::CONST:
328 case Token::VAR:
329 return ParseVariableStatement(ok);
330
331 case Token::SEMICOLON:
332 Next();
333 return kUnknownStatement;
334
335 case Token::IF:
336 return ParseIfStatement(ok);
337
338 case Token::DO:
339 return ParseDoWhileStatement(ok);
340
341 case Token::WHILE:
342 return ParseWhileStatement(ok);
343
344 case Token::FOR:
345 return ParseForStatement(ok);
346
347 case Token::CONTINUE:
348 return ParseContinueStatement(ok);
349
350 case Token::BREAK:
351 return ParseBreakStatement(ok);
352
353 case Token::RETURN:
354 return ParseReturnStatement(ok);
355
356 case Token::WITH:
357 return ParseWithStatement(ok);
358
359 case Token::SWITCH:
360 return ParseSwitchStatement(ok);
361
362 case Token::THROW:
363 return ParseThrowStatement(ok);
364
365 case Token::TRY:
366 return ParseTryStatement(ok);
367
368 case Token::FUNCTION:
369 return ParseFunctionDeclaration(ok);
370
371 case Token::NATIVE:
372 return ParseNativeDeclaration(ok);
373
374 case Token::DEBUGGER:
375 return ParseDebuggerStatement(ok);
376
377 default:
378 return ParseExpressionOrLabelledStatement(ok);
379 }
380 }
381
382
383 template <typename Scanner, typename Log>
384 Statement PreParser<Scanner, Log>::ParseFunctionDeclaration(bool* ok) {
385 // FunctionDeclaration ::
386 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
387 Expect(Token::FUNCTION, CHECK_OK);
388 ParseIdentifier(CHECK_OK);
389 ParseFunctionLiteral(CHECK_OK);
390 return kUnknownStatement;
391 }
392
393
394 // Language extension which is only enabled for source files loaded
395 // through the API's extension mechanism. A native function
396 // declaration is resolved by looking up the function through a
397 // callback provided by the extension.
398 template <typename Scanner, typename Log>
399 Statement PreParser<Scanner, Log>::ParseNativeDeclaration(bool* ok) {
400 Expect(Token::NATIVE, CHECK_OK);
401 Expect(Token::FUNCTION, CHECK_OK);
402 ParseIdentifier(CHECK_OK);
403 Expect(Token::LPAREN, CHECK_OK);
404 bool done = (peek() == Token::RPAREN);
405 while (!done) {
406 ParseIdentifier(CHECK_OK);
407 done = (peek() == Token::RPAREN);
408 if (!done) {
409 Expect(Token::COMMA, CHECK_OK);
410 }
411 }
412 Expect(Token::RPAREN, CHECK_OK);
413 Expect(Token::SEMICOLON, CHECK_OK);
414 return kUnknownStatement;
415 }
416
417
418 template <typename Scanner, typename Log>
419 Statement PreParser<Scanner, Log>::ParseBlock(bool* ok) {
420 // Block ::
421 // '{' Statement* '}'
422
423 // Note that a Block does not introduce a new execution scope!
424 // (ECMA-262, 3rd, 12.2)
425 //
426 Expect(Token::LBRACE, CHECK_OK);
427 while (peek() != Token::RBRACE) {
428 ParseStatement(CHECK_OK);
429 }
430 Expect(Token::RBRACE, CHECK_OK);
431 return kUnknownStatement;
432 }
433
434
435 template <typename Scanner, typename Log>
436 Statement PreParser<Scanner, Log>::ParseVariableStatement(bool* ok) {
437 // VariableStatement ::
438 // VariableDeclarations ';'
439
440 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
441 ExpectSemicolon(CHECK_OK);
442 return result;
443 }
444
445
446 // If the variable declaration declares exactly one non-const
447 // variable, then *var is set to that variable. In all other cases,
448 // *var is untouched; in particular, it is the caller's responsibility
449 // to initialize it properly. This mechanism is also used for the parsing
450 // of 'for-in' loops.
451 template <typename Scanner, typename Log>
452 Statement PreParser<Scanner, Log>::ParseVariableDeclarations(bool accept_IN,
453 int* num_decl,
454 bool* ok) {
455 // VariableDeclarations ::
456 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
457
458 if (peek() == Token::VAR) {
459 Consume(Token::VAR);
460 } else if (peek() == Token::CONST) {
461 Consume(Token::CONST);
462 } else {
463 *ok = false;
464 return 0;
465 }
466
467 // The scope of a variable/const declared anywhere inside a function
468 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
469 int nvars = 0; // the number of variables declared
470 do {
471 // Parse variable name.
472 if (nvars > 0) Consume(Token::COMMA);
473 ParseIdentifier(CHECK_OK);
474 nvars++;
475 if (peek() == Token::ASSIGN) {
476 Expect(Token::ASSIGN, CHECK_OK);
477 ParseAssignmentExpression(accept_IN, CHECK_OK);
478 }
479 } while (peek() == Token::COMMA);
480
481 if (num_decl != NULL) *num_decl = nvars;
482 return kUnknownStatement;
483 }
484
485
486 template <typename Scanner, typename Log>
487 Statement PreParser<Scanner, Log>::ParseExpressionOrLabelledStatement(
488 bool* ok) {
489 // ExpressionStatement | LabelledStatement ::
490 // Expression ';'
491 // Identifier ':' Statement
492
493 Expression expr = ParseExpression(true, CHECK_OK);
494 if (peek() == Token::COLON && expr == kIdentifierExpression) {
495 Consume(Token::COLON);
496 return ParseStatement(ok);
497 }
498 // Parsed expression statement.
499 ExpectSemicolon(CHECK_OK);
500 return kUnknownStatement;
501 }
502
503
504 template <typename Scanner, typename Log>
505 Statement PreParser<Scanner, Log>::ParseIfStatement(bool* ok) {
506 // IfStatement ::
507 // 'if' '(' Expression ')' Statement ('else' Statement)?
508
509 Expect(Token::IF, CHECK_OK);
510 Expect(Token::LPAREN, CHECK_OK);
511 ParseExpression(true, CHECK_OK);
512 Expect(Token::RPAREN, CHECK_OK);
513 ParseStatement(CHECK_OK);
514 if (peek() == Token::ELSE) {
515 Next();
516 ParseStatement(CHECK_OK);
517 }
518 return kUnknownStatement;
519 }
520
521
522 template <typename Scanner, typename Log>
523 Statement PreParser<Scanner, Log>::ParseContinueStatement(bool* ok) {
524 // ContinueStatement ::
525 // 'continue' [no line terminator] Identifier? ';'
526
527 Expect(Token::CONTINUE, CHECK_OK);
528 Token::Value tok = peek();
529 if (!scanner_->has_line_terminator_before_next() &&
530 tok != Token::SEMICOLON &&
531 tok != Token::RBRACE &&
532 tok != Token::EOS) {
533 ParseIdentifier(CHECK_OK);
534 }
535 ExpectSemicolon(CHECK_OK);
536 return kUnknownStatement;
537 }
538
539
540 template <typename Scanner, typename Log>
541 Statement PreParser<Scanner, Log>::ParseBreakStatement(bool* ok) {
542 // BreakStatement ::
543 // 'break' [no line terminator] Identifier? ';'
544
545 Expect(Token::BREAK, CHECK_OK);
546 Token::Value tok = peek();
547 if (!scanner_->has_line_terminator_before_next() &&
548 tok != Token::SEMICOLON &&
549 tok != Token::RBRACE &&
550 tok != Token::EOS) {
551 ParseIdentifier(CHECK_OK);
552 }
553 ExpectSemicolon(CHECK_OK);
554 return kUnknownStatement;
555 }
556
557
558 template <typename Scanner, typename Log>
559 Statement PreParser<Scanner, Log>::ParseReturnStatement(bool* ok) {
560 // ReturnStatement ::
561 // 'return' [no line terminator] Expression? ';'
562
563 // Consume the return token. It is necessary to do the before
564 // reporting any errors on it, because of the way errors are
565 // reported (underlining).
566 Expect(Token::RETURN, CHECK_OK);
567
568 // An ECMAScript program is considered syntactically incorrect if it
569 // contains a return statement that is not within the body of a
570 // function. See ECMA-262, section 12.9, page 67.
571 // This is not handled during preparsing.
572
573 Token::Value tok = peek();
574 if (!scanner_->has_line_terminator_before_next() &&
575 tok != Token::SEMICOLON &&
576 tok != Token::RBRACE &&
577 tok != Token::EOS) {
578 ParseExpression(true, CHECK_OK);
579 }
580 ExpectSemicolon(CHECK_OK);
581 return kUnknownStatement;
582 }
583
584
585 template <typename Scanner, typename Log>
586 Statement PreParser<Scanner, Log>::ParseWithStatement(bool* ok) {
587 // WithStatement ::
588 // 'with' '(' Expression ')' Statement
589 Expect(Token::WITH, CHECK_OK);
590 Expect(Token::LPAREN, CHECK_OK);
591 ParseExpression(true, CHECK_OK);
592 Expect(Token::RPAREN, CHECK_OK);
593
594 scope_->EnterWith();
595 ParseStatement(CHECK_OK);
596 scope_->LeaveWith();
597 return kUnknownStatement;
598 }
599
600
601 template <typename Scanner, typename Log>
602 Statement PreParser<Scanner, Log>::ParseSwitchStatement(bool* ok) {
603 // SwitchStatement ::
604 // 'switch' '(' Expression ')' '{' CaseClause* '}'
605
606 Expect(Token::SWITCH, CHECK_OK);
607 Expect(Token::LPAREN, CHECK_OK);
608 ParseExpression(true, CHECK_OK);
609 Expect(Token::RPAREN, CHECK_OK);
610
611 Expect(Token::LBRACE, CHECK_OK);
612 Token::Value token = peek();
613 while (token != Token::RBRACE) {
614 if (token == Token::CASE) {
615 Expect(Token::CASE, CHECK_OK);
616 ParseExpression(true, CHECK_OK);
617 Expect(Token::COLON, CHECK_OK);
618 } else if (token == Token::DEFAULT) {
619 Expect(Token::DEFAULT, CHECK_OK);
620 Expect(Token::COLON, CHECK_OK);
621 } else {
622 ParseStatement(CHECK_OK);
623 }
624 token = peek();
625 }
626 Expect(Token::RBRACE, CHECK_OK);
627
628 return kUnknownStatement;
629 }
630
631
632 template <typename Scanner, typename Log>
633 Statement PreParser<Scanner, Log>::ParseDoWhileStatement(bool* ok) {
634 // DoStatement ::
635 // 'do' Statement 'while' '(' Expression ')' ';'
636
637 Expect(Token::DO, CHECK_OK);
638 ParseStatement(CHECK_OK);
639 Expect(Token::WHILE, CHECK_OK);
640 Expect(Token::LPAREN, CHECK_OK);
641 ParseExpression(true, CHECK_OK);
642 Expect(Token::RPAREN, CHECK_OK);
643 return kUnknownStatement;
644 }
645
646
647 template <typename Scanner, typename Log>
648 Statement PreParser<Scanner, Log>::ParseWhileStatement(bool* ok) {
649 // WhileStatement ::
650 // 'while' '(' Expression ')' Statement
651
652 Expect(Token::WHILE, CHECK_OK);
653 Expect(Token::LPAREN, CHECK_OK);
654 ParseExpression(true, CHECK_OK);
655 Expect(Token::RPAREN, CHECK_OK);
656 ParseStatement(CHECK_OK);
657 return kUnknownStatement;
658 }
659
660
661 template <typename Scanner, typename Log>
662 Statement PreParser<Scanner, Log>::ParseForStatement(bool* ok) {
663 // ForStatement ::
664 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
665
666 Expect(Token::FOR, CHECK_OK);
667 Expect(Token::LPAREN, CHECK_OK);
668 if (peek() != Token::SEMICOLON) {
669 if (peek() == Token::VAR || peek() == Token::CONST) {
670 int decl_count;
671 ParseVariableDeclarations(false, &decl_count, CHECK_OK);
672 if (peek() == Token::IN && decl_count == 1) {
673 Expect(Token::IN, CHECK_OK);
674 ParseExpression(true, CHECK_OK);
675 Expect(Token::RPAREN, CHECK_OK);
676
677 ParseStatement(CHECK_OK);
678 return kUnknownStatement;
679 }
680 } else {
681 ParseExpression(false, CHECK_OK);
682 if (peek() == Token::IN) {
683 Expect(Token::IN, CHECK_OK);
684 ParseExpression(true, CHECK_OK);
685 Expect(Token::RPAREN, CHECK_OK);
686
687 ParseStatement(CHECK_OK);
688 return kUnknownStatement;
689 }
690 }
691 }
692
693 // Parsed initializer at this point.
694 Expect(Token::SEMICOLON, CHECK_OK);
695
696 if (peek() != Token::SEMICOLON) {
697 ParseExpression(true, CHECK_OK);
698 }
699 Expect(Token::SEMICOLON, CHECK_OK);
700
701 if (peek() != Token::RPAREN) {
702 ParseExpression(true, CHECK_OK);
703 }
704 Expect(Token::RPAREN, CHECK_OK);
705
706 ParseStatement(CHECK_OK);
707 return kUnknownStatement;
708 }
709
710
711 template <typename Scanner, typename Log>
712 Statement PreParser<Scanner, Log>::ParseThrowStatement(bool* ok) {
713 // ThrowStatement ::
714 // 'throw' [no line terminator] Expression ';'
715
716 Expect(Token::THROW, CHECK_OK);
717 if (scanner_->has_line_terminator_before_next()) {
718 typename Scanner::Location pos = scanner_->location();
719 ReportMessageAt(pos.beg_pos, pos.end_pos,
720 "newline_after_throw", NULL);
721 *ok = false;
722 return NULL;
723 }
724 ParseExpression(true, CHECK_OK);
725 ExpectSemicolon(CHECK_OK);
726
727 return kUnknownStatement;
728 }
729
730
731 template <typename Scanner, typename Log>
732 Statement PreParser<Scanner, Log>::ParseTryStatement(bool* ok) {
733 // TryStatement ::
734 // 'try' Block Catch
735 // 'try' Block Finally
736 // 'try' Block Catch Finally
737 //
738 // Catch ::
739 // 'catch' '(' Identifier ')' Block
740 //
741 // Finally ::
742 // 'finally' Block
743
744 // In preparsing, allow any number of catch/finally blocks, including zero
745 // of both.
746
747 Expect(Token::TRY, CHECK_OK);
748
749 ParseBlock(CHECK_OK);
750
751 bool catch_or_finally_seen = false;
752 if (peek() == Token::CATCH) {
753 Expect(Token::CATCH, CHECK_OK);
754 Expect(Token::LPAREN, CHECK_OK);
755 ParseIdentifier(CHECK_OK);
756 Expect(Token::RPAREN, CHECK_OK);
757 ParseBlock(CHECK_OK);
758 catch_or_finally_seen = true;
759 }
760 if (peek() == Token::FINALLY) {
761 Expect(Token::FINALLY, CHECK_OK);
762 ParseBlock(CHECK_OK);
763 catch_or_finally_seen = true;
764 }
765 if (!catch_or_finally_seen) {
766 *ok = false;
767 }
768 return kUnknownStatement;
769 }
770
771
772 template <typename Scanner, typename Log>
773 Statement PreParser<Scanner, Log>::ParseDebuggerStatement(bool* ok) {
774 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
775 // contexts this is used as a statement which invokes the debugger as if a
776 // break point is present.
777 // DebuggerStatement ::
778 // 'debugger' ';'
779
780 Expect(Token::DEBUGGER, CHECK_OK);
781 ExpectSemicolon(CHECK_OK);
782 return kUnknownStatement;
783 }
784
785
786 // Precedence = 1
787 template <typename Scanner, typename Log>
788 Expression PreParser<Scanner, Log>::ParseExpression(bool accept_IN, bool* ok) {
789 // Expression ::
790 // AssignmentExpression
791 // Expression ',' AssignmentExpression
792
793 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
794 while (peek() == Token::COMMA) {
795 Expect(Token::COMMA, CHECK_OK);
796 ParseAssignmentExpression(accept_IN, CHECK_OK);
797 result = kUnknownExpression;
798 }
799 return result;
800 }
801
802
803 // Precedence = 2
804 template <typename Scanner, typename Log>
805 Expression PreParser<Scanner, Log>::ParseAssignmentExpression(bool accept_IN,
806 bool* ok) {
807 // AssignmentExpression ::
808 // ConditionalExpression
809 // LeftHandSideExpression AssignmentOperator AssignmentExpression
810
811 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
812
813 if (!Token::IsAssignmentOp(peek())) {
814 // Parsed conditional expression only (no assignment).
815 return expression;
816 }
817
818 Token::Value op = Next(); // Get assignment operator.
819 ParseAssignmentExpression(accept_IN, CHECK_OK);
820
821 if ((op == Token::ASSIGN) && (expression == kThisPropertyExpression)) {
822 scope_->AddProperty();
823 }
824
825 return kUnknownExpression;
826 }
827
828
829 // Precedence = 3
830 template <typename Scanner, typename Log>
831 Expression PreParser<Scanner, Log>::ParseConditionalExpression(bool accept_IN,
832 bool* ok) {
833 // ConditionalExpression ::
834 // LogicalOrExpression
835 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
836
837 // We start using the binary expression parser for prec >= 4 only!
838 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
839 if (peek() != Token::CONDITIONAL) return expression;
840 Consume(Token::CONDITIONAL);
841 // In parsing the first assignment expression in conditional
842 // expressions we always accept the 'in' keyword; see ECMA-262,
843 // section 11.12, page 58.
844 ParseAssignmentExpression(true, CHECK_OK);
845 Expect(Token::COLON, CHECK_OK);
846 ParseAssignmentExpression(accept_IN, CHECK_OK);
847 return kUnknownExpression;
848 }
849
850
851 template <typename Scanner, typename Log>
852 int PreParser<Scanner, Log>::Precedence(Token::Value tok, bool accept_IN) {
853 if (tok == Token::IN && !accept_IN)
854 return 0; // 0 precedence will terminate binary expression parsing
855
856 return Token::Precedence(tok);
857 }
858
859
860 // Precedence >= 4
861 template <typename Scanner, typename Log>
862 Expression PreParser<Scanner, Log>::ParseBinaryExpression(int prec,
863 bool accept_IN,
864 bool* ok) {
865 Expression result = ParseUnaryExpression(CHECK_OK);
866 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
867 // prec1 >= 4
868 while (Precedence(peek(), accept_IN) == prec1) {
869 Next();
870 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
871 result = kUnknownExpression;
872 }
873 }
874 return result;
875 }
876
877
878 template <typename Scanner, typename Log>
879 Expression PreParser<Scanner, Log>::ParseUnaryExpression(bool* ok) {
880 // UnaryExpression ::
881 // PostfixExpression
882 // 'delete' UnaryExpression
883 // 'void' UnaryExpression
884 // 'typeof' UnaryExpression
885 // '++' UnaryExpression
886 // '--' UnaryExpression
887 // '+' UnaryExpression
888 // '-' UnaryExpression
889 // '~' UnaryExpression
890 // '!' UnaryExpression
891
892 Token::Value op = peek();
893 if (Token::IsUnaryOp(op) || Token::IsCountOp(op)) {
894 op = Next();
895 ParseUnaryExpression(ok);
896 return kUnknownExpression;
897 } else {
898 return ParsePostfixExpression(ok);
899 }
900 }
901
902
903 template <typename Scanner, typename Log>
904 Expression PreParser<Scanner, Log>::ParsePostfixExpression(bool* ok) {
905 // PostfixExpression ::
906 // LeftHandSideExpression ('++' | '--')?
907
908 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
909 if (!scanner_->has_line_terminator_before_next() &&
910 Token::IsCountOp(peek())) {
911 Next();
912 return kUnknownExpression;
913 }
914 return expression;
915 }
916
917
918 template <typename Scanner, typename Log>
919 Expression PreParser<Scanner, Log>::ParseLeftHandSideExpression(bool* ok) {
920 // LeftHandSideExpression ::
921 // (NewExpression | MemberExpression) ...
922
923 Expression result;
924 if (peek() == Token::NEW) {
925 result = ParseNewExpression(CHECK_OK);
926 } else {
927 result = ParseMemberExpression(CHECK_OK);
928 }
929
930 while (true) {
931 switch (peek()) {
932 case Token::LBRACK: {
933 Consume(Token::LBRACK);
934 ParseExpression(true, CHECK_OK);
935 Expect(Token::RBRACK, CHECK_OK);
936 if (result == kThisExpression) {
937 result = kThisPropertyExpression;
938 } else {
939 result = kUnknownExpression;
940 }
941 break;
942 }
943
944 case Token::LPAREN: {
945 ParseArguments(CHECK_OK);
946 result = kUnknownExpression;
947 break;
948 }
949
950 case Token::PERIOD: {
951 Consume(Token::PERIOD);
952 ParseIdentifierName(CHECK_OK);
953 if (result == kThisExpression) {
954 result = kThisPropertyExpression;
955 } else {
956 result = kUnknownExpression;
957 }
958 break;
959 }
960
961 default:
962 return result;
963 }
964 }
965 }
966
967
968
969 template <typename Scanner, typename Log>
970 Expression PreParser<Scanner, Log>::ParseNewPrefix(int* new_count, bool* ok) {
971 // NewExpression ::
972 // ('new')+ MemberExpression
973
974 // The grammar for new expressions is pretty warped. The keyword
975 // 'new' can either be a part of the new expression (where it isn't
976 // followed by an argument list) or a part of the member expression,
977 // where it must be followed by an argument list. To accommodate
978 // this, we parse the 'new' keywords greedily and keep track of how
979 // many we have parsed. This information is then passed on to the
980 // member expression parser, which is only allowed to match argument
981 // lists as long as it has 'new' prefixes left
982 Expect(Token::NEW, CHECK_OK);
983 *new_count++;
984
985 if (peek() == Token::NEW) {
986 ParseNewPrefix(new_count, CHECK_OK);
987 } else {
988 ParseMemberWithNewPrefixesExpression(new_count, CHECK_OK);
989 }
990
991 if (*new_count > 0) {
992 *new_count--;
993 }
994 return kUnknownExpression;
995 }
996
997
998 template <typename Scanner, typename Log>
999 Expression PreParser<Scanner, Log>::ParseNewExpression(bool* ok) {
1000 int new_count = 0;
1001 return ParseNewPrefix(&new_count, ok);
1002 }
1003
1004
1005 template <typename Scanner, typename Log>
1006 Expression PreParser<Scanner, Log>::ParseMemberExpression(bool* ok) {
1007 return ParseMemberWithNewPrefixesExpression(NULL, ok);
1008 }
1009
1010
1011 template <typename Scanner, typename Log>
1012 Expression PreParser<Scanner, Log>::ParseMemberWithNewPrefixesExpression(
1013 int* new_count, bool* ok) {
1014 // MemberExpression ::
1015 // (PrimaryExpression | FunctionLiteral)
1016 // ('[' Expression ']' | '.' Identifier | Arguments)*
1017
1018 // Parse the initial primary or function expression.
1019 Expression result = NULL;
1020 if (peek() == Token::FUNCTION) {
1021 Consume(Token::FUNCTION);
1022 if (peek() == Token::IDENTIFIER) {
1023 ParseIdentifier(CHECK_OK);
1024 }
1025 result = ParseFunctionLiteral(CHECK_OK);
1026 } else {
1027 result = ParsePrimaryExpression(CHECK_OK);
1028 }
1029
1030 while (true) {
1031 switch (peek()) {
1032 case Token::LBRACK: {
1033 Consume(Token::LBRACK);
1034 ParseExpression(true, CHECK_OK);
1035 Expect(Token::RBRACK, CHECK_OK);
1036 if (result == kThisExpression) {
1037 result = kThisPropertyExpression;
1038 } else {
1039 result = kUnknownExpression;
1040 }
1041 break;
1042 }
1043 case Token::PERIOD: {
1044 Consume(Token::PERIOD);
1045 ParseIdentifierName(CHECK_OK);
1046 if (result == kThisExpression) {
1047 result = kThisPropertyExpression;
1048 } else {
1049 result = kUnknownExpression;
1050 }
1051 break;
1052 }
1053 case Token::LPAREN: {
1054 if ((new_count == NULL) || *new_count == 0) return result;
1055 // Consume one of the new prefixes (already parsed).
1056 ParseArguments(CHECK_OK);
1057 *new_count--;
1058 result = kUnknownExpression;
1059 break;
1060 }
1061 default:
1062 return result;
1063 }
1064 }
1065 }
1066
1067
1068 template <typename Scanner, typename Log>
1069 Expression PreParser<Scanner, Log>::ParsePrimaryExpression(bool* ok) {
1070 // PrimaryExpression ::
1071 // 'this'
1072 // 'null'
1073 // 'true'
1074 // 'false'
1075 // Identifier
1076 // Number
1077 // String
1078 // ArrayLiteral
1079 // ObjectLiteral
1080 // RegExpLiteral
1081 // '(' Expression ')'
1082
1083 Expression result = kUnknownExpression;
1084 switch (peek()) {
1085 case Token::THIS: {
1086 Next();
1087 result = kThisExpression;
1088 break;
1089 }
1090
1091 case Token::IDENTIFIER: {
1092 ParseIdentifier(CHECK_OK);
1093 result = kIdentifierExpression;
1094 break;
1095 }
1096
1097 case Token::NULL_LITERAL:
1098 case Token::TRUE_LITERAL:
1099 case Token::FALSE_LITERAL:
1100 case Token::NUMBER: {
1101 Next();
1102 break;
1103 }
1104 case Token::STRING: {
1105 Next();
1106 result = GetStringSymbol();
1107 break;
1108 }
1109
1110 case Token::ASSIGN_DIV:
1111 result = ParseRegExpLiteral(true, CHECK_OK);
1112 break;
1113
1114 case Token::DIV:
1115 result = ParseRegExpLiteral(false, CHECK_OK);
1116 break;
1117
1118 case Token::LBRACK:
1119 result = ParseArrayLiteral(CHECK_OK);
1120 break;
1121
1122 case Token::LBRACE:
1123 result = ParseObjectLiteral(CHECK_OK);
1124 break;
1125
1126 case Token::LPAREN:
1127 Consume(Token::LPAREN);
1128 result = ParseExpression(true, CHECK_OK);
1129 Expect(Token::RPAREN, CHECK_OK);
1130 if (result == kIdentifierExpression) result = kUnknownExpression;
1131 break;
1132
1133 case Token::MOD:
1134 result = ParseV8Intrinsic(CHECK_OK);
1135 break;
1136
1137 default: {
1138 Next();
1139 *ok = false;
1140 return kUnknownExpression;
1141 }
1142 }
1143
1144 return result;
1145 }
1146
1147
1148 template <typename Scanner, typename Log>
1149 Expression PreParser<Scanner, Log>::ParseArrayLiteral(bool* ok) {
1150 // ArrayLiteral ::
1151 // '[' Expression? (',' Expression?)* ']'
1152 Expect(Token::LBRACK, CHECK_OK);
1153 while (peek() != Token::RBRACK) {
1154 if (peek() != Token::COMMA) {
1155 ParseAssignmentExpression(true, CHECK_OK);
1156 }
1157 if (peek() != Token::RBRACK) {
1158 Expect(Token::COMMA, CHECK_OK);
1159 }
1160 }
1161 Expect(Token::RBRACK, CHECK_OK);
1162
1163 scope_->NextMaterializedLiteralIndex();
1164 return kUnknownExpression;
1165 }
1166
1167
1168 template <typename Scanner, typename Log>
1169 Expression PreParser<Scanner, Log>::ParseObjectLiteral(bool* ok) {
1170 // ObjectLiteral ::
1171 // '{' (
1172 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1173 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1174 // )*[','] '}'
1175
1176 Expect(Token::LBRACE, CHECK_OK);
1177 while (peek() != Token::RBRACE) {
1178 Token::Value next = peek();
1179 switch (next) {
1180 case Token::IDENTIFIER: {
1181 bool is_getter = false;
1182 bool is_setter = false;
1183 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1184 if ((is_getter || is_setter) && peek() != Token::COLON) {
1185 Token::Value name = Next();
1186 if (name != Token::IDENTIFIER &&
1187 name != Token::NUMBER &&
1188 name != Token::STRING &&
1189 !Token::IsKeyword(name)) {
1190 *ok = false;
1191 return kUnknownExpression;
1192 }
1193 ParseFunctionLiteral(CHECK_OK);
1194 if (peek() != Token::RBRACE) {
1195 Expect(Token::COMMA, CHECK_OK);
1196 }
1197 continue; // restart the while
1198 }
1199 break;
1200 }
1201 case Token::STRING:
1202 Consume(next);
1203 GetStringSymbol();
1204 break;
1205 case Token::NUMBER:
1206 Consume(next);
1207 break;
1208 default:
1209 if (Token::IsKeyword(next)) {
1210 Consume(next);
1211 } else {
1212 // Unexpected token.
1213 *ok = false;
1214 return kUnknownExpression;
1215 }
1216 }
1217
1218 Expect(Token::COLON, CHECK_OK);
1219 ParseAssignmentExpression(true, CHECK_OK);
1220
1221 // TODO(1240767): Consider allowing trailing comma.
1222 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
1223 }
1224 Expect(Token::RBRACE, CHECK_OK);
1225
1226 scope_->NextMaterializedLiteralIndex();
1227 return kUnknownExpression;
1228 }
1229
1230
1231 template <typename Scanner, typename Log>
1232 Expression PreParser<Scanner, Log>::ParseRegExpLiteral(bool seen_equal,
1233 bool* ok) {
1234 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1235 Next();
1236 typename Scanner::Location location = scanner_->location();
1237 ReportMessageAt(location.beg_pos, location.end_pos,
1238 "unterminated_regexp", NULL);
1239 *ok = false;
1240 return kUnknownExpression;
1241 }
1242
1243 scope_->NextMaterializedLiteralIndex();
1244
1245 if (!scanner_->ScanRegExpFlags()) {
1246 Next();
1247 typename Scanner::Location location = scanner_->location();
1248 ReportMessageAt(location.beg_pos, location.end_pos,
1249 "invalid_regexp_flags", NULL);
1250 *ok = false;
1251 return kUnknownExpression;
1252 }
1253 Next();
1254 return kUnknownExpression;
1255 }
1256
1257
1258 template <typename Scanner, typename Log>
1259 Arguments PreParser<Scanner, Log>::ParseArguments(bool* ok) {
1260 // Arguments ::
1261 // '(' (AssignmentExpression)*[','] ')'
1262
1263 Expect(Token::LPAREN, CHECK_OK);
1264 bool done = (peek() == Token::RPAREN);
1265 int argc = 0;
1266 while (!done) {
1267 ParseAssignmentExpression(true, CHECK_OK);
1268 argc++;
1269 done = (peek() == Token::RPAREN);
1270 if (!done) Expect(Token::COMMA, CHECK_OK);
1271 }
1272 Expect(Token::RPAREN, CHECK_OK);
1273 return argc;
1274 }
1275
1276
1277 template <typename Scanner, typename Log>
1278 Expression PreParser<Scanner, Log>::ParseFunctionLiteral(bool* ok) {
1279 // Function ::
1280 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1281
1282 // Parse function body.
1283 ScopeType outer_scope_type = scope_->type();
1284 bool inside_with = scope_->IsInsideWith();
1285 Scope function_scope(&scope_, kFunctionScope);
1286
1287 // FormalParameterList ::
1288 // '(' (Identifier)*[','] ')'
1289 Expect(Token::LPAREN, CHECK_OK);
1290 bool done = (peek() == Token::RPAREN);
1291 while (!done) {
1292 ParseIdentifier(CHECK_OK);
1293 done = (peek() == Token::RPAREN);
1294 if (!done) {
1295 Expect(Token::COMMA, CHECK_OK);
1296 }
1297 }
1298 Expect(Token::RPAREN, CHECK_OK);
1299
1300 Expect(Token::LBRACE, CHECK_OK);
1301 int function_block_pos = scanner_->location().beg_pos;
1302
1303 // Determine if the function will be lazily compiled.
1304 // Currently only happens to top-level functions.
1305 // Optimistically assume that all top-level functions are lazily compiled.
1306 bool is_lazily_compiled =
1307 (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_);
1308
1309 if (is_lazily_compiled) {
1310 log_->PauseRecording();
1311 ParseSourceElements(Token::RBRACE, ok);
1312 log_->ResumeRecording();
1313 if (!*ok) return kUnknownExpression;
1314
1315 Expect(Token::RBRACE, CHECK_OK);
1316
1317 int end_pos = scanner_->location().end_pos;
1318 log_->LogFunction(function_block_pos, end_pos,
1319 function_scope.materialized_literal_count(),
1320 function_scope.expected_properties());
1321 } else {
1322 ParseSourceElements(Token::RBRACE, CHECK_OK);
1323 Expect(Token::RBRACE, CHECK_OK);
1324 }
1325 return kUnknownExpression;
1326 }
1327
1328
1329 template <typename Scanner, typename Log>
1330 Expression PreParser<Scanner, Log>::ParseV8Intrinsic(bool* ok) {
1331 // CallRuntime ::
1332 // '%' Identifier Arguments
1333
1334 Expect(Token::MOD, CHECK_OK);
1335 ParseIdentifier(CHECK_OK);
1336 ParseArguments(CHECK_OK);
1337
1338 return kUnknownExpression;
1339 }
1340
1341
1342 template <typename Scanner, typename Log>
1343 void PreParser<Scanner, Log>::ExpectSemicolon(bool* ok) {
1344 // Check for automatic semicolon insertion according to
1345 // the rules given in ECMA-262, section 7.9, page 21.
1346 Token::Value tok = peek();
1347 if (tok == Token::SEMICOLON) {
1348 Next();
1349 return;
1350 }
1351 if (scanner_->has_line_terminator_before_next() ||
1352 tok == Token::RBRACE ||
1353 tok == Token::EOS) {
1354 return;
1355 }
1356 Expect(Token::SEMICOLON, ok);
1357 }
1358
1359
1360 template <typename Scanner, typename Log>
1361 Identifier PreParser<Scanner, Log>::GetIdentifierSymbol() {
1362 const char* literal_chars = scanner_->literal_string();
1363 int literal_length = scanner_->literal_length();
1364 int identifier_pos = scanner_->location().beg_pos;
1365
1366 log_->LogSymbol(identifier_pos, literal_chars, literal_length);
1367
1368 return kUnknownExpression;
1369 }
1370
1371
1372 template <typename Scanner, typename Log>
1373 Expression PreParser<Scanner, Log>::GetStringSymbol() {
1374 const char* literal_chars = scanner_->literal_string();
1375 int literal_length = scanner_->literal_length();
1376
1377 int literal_position = scanner_->location().beg_pos;
1378 log_->LogSymbol(literal_position, literal_chars, literal_length);
1379
1380 return kUnknownExpression;
1381 }
1382
1383
1384 template <typename Scanner, typename Log>
1385 Identifier PreParser<Scanner, Log>::ParseIdentifier(bool* ok) {
1386 Expect(Token::IDENTIFIER, ok);
1387 return GetIdentifierSymbol();
1388 }
1389
1390
1391 template <typename Scanner, typename Log>
1392 Identifier PreParser<Scanner, Log>::ParseIdentifierName(bool* ok) {
1393 Token::Value next = Next();
1394 if (Token::IsKeyword(next)) {
1395 int pos = scanner_->location().beg_pos;
1396 const char* keyword = Token::String(next);
1397 log_->LogSymbol(pos, keyword, strlen(keyword));
1398 return kUnknownExpression;
1399 }
1400 if (next == Token::IDENTIFIER) {
1401 return GetIdentifierSymbol();
1402 }
1403 *ok = false;
1404 return kUnknownIdentifier;
1405 }
1406
1407
1408 // This function reads an identifier and determines whether or not it
1409 // is 'get' or 'set'. The reason for not using ParseIdentifier and
1410 // checking on the output is that this involves heap allocation which
1411 // we can't do during preparsing.
1412 template <typename Scanner, typename Log>
1413 Identifier PreParser<Scanner, Log>::ParseIdentifierOrGetOrSet(bool* is_get,
1414 bool* is_set,
1415 bool* ok) {
1416 Expect(Token::IDENTIFIER, CHECK_OK);
1417 if (scanner_->literal_length() == 3) {
1418 const char* token = scanner_->literal_string();
1419 *is_get = strncmp(token, "get", 3) == 0;
1420 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1421 }
1422 return GetIdentifierSymbol();
1423 }
1424
1425 #undef CHECK_OK
1426 } } } // v8::internal::preparser
1427
1428 #endif // V8_PREPARSER_H
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698