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

Side by Side Diff: src/preparser.cc

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

Powered by Google App Engine
This is Rietveld 408576698