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