OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 16 matching lines...) Expand all Loading... |
28 // Features shared by parsing and pre-parsing scanners. | 28 // Features shared by parsing and pre-parsing scanners. |
29 | 29 |
30 #include "../include/v8stdint.h" | 30 #include "../include/v8stdint.h" |
31 #include "scanner-base.h" | 31 #include "scanner-base.h" |
32 #include "char-predicates-inl.h" | 32 #include "char-predicates-inl.h" |
33 | 33 |
34 namespace v8 { | 34 namespace v8 { |
35 namespace internal { | 35 namespace internal { |
36 | 36 |
37 // ---------------------------------------------------------------------------- | 37 // ---------------------------------------------------------------------------- |
38 // Compound predicates. | |
39 | |
40 bool ScannerConstants::IsIdentifier(unibrow::CharacterStream* buffer) { | |
41 // Checks whether the buffer contains an identifier (no escape). | |
42 if (!buffer->has_more()) return false; | |
43 if (!kIsIdentifierStart.get(buffer->GetNext())) { | |
44 return false; | |
45 } | |
46 while (buffer->has_more()) { | |
47 if (!kIsIdentifierPart.get(buffer->GetNext())) { | |
48 return false; | |
49 } | |
50 } | |
51 return true; | |
52 } | |
53 | |
54 // ---------------------------------------------------------------------------- | |
55 // Scanner | 38 // Scanner |
56 | 39 |
57 Scanner::Scanner(ScannerConstants* scanner_constants) | 40 Scanner::Scanner(UnicodeCache* unicode_cache) |
58 : scanner_constants_(scanner_constants), | 41 : unicode_cache_(unicode_cache), |
59 octal_pos_(kNoOctalLocation) { | 42 octal_pos_(kNoOctalLocation) { } |
60 } | |
61 | 43 |
62 | 44 |
63 uc32 Scanner::ScanHexEscape(uc32 c, int length) { | 45 uc32 Scanner::ScanHexEscape(uc32 c, int length) { |
64 ASSERT(length <= 4); // prevent overflow | 46 ASSERT(length <= 4); // prevent overflow |
65 | 47 |
66 uc32 digits[4]; | 48 uc32 digits[4]; |
67 uc32 x = 0; | 49 uc32 x = 0; |
68 for (int i = 0; i < length; i++) { | 50 for (int i = 0; i < length; i++) { |
69 digits[i] = c0_; | 51 digits[i] = c0_; |
70 int d = HexValue(c0_); | 52 int d = HexValue(c0_); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 if (c != '0' || i > 0) { | 89 if (c != '0' || i > 0) { |
108 octal_pos_ = source_pos() - i - 1; // Already advanced | 90 octal_pos_ = source_pos() - i - 1; // Already advanced |
109 } | 91 } |
110 return x; | 92 return x; |
111 } | 93 } |
112 | 94 |
113 | 95 |
114 // ---------------------------------------------------------------------------- | 96 // ---------------------------------------------------------------------------- |
115 // JavaScriptScanner | 97 // JavaScriptScanner |
116 | 98 |
117 JavaScriptScanner::JavaScriptScanner(ScannerConstants* scanner_contants) | 99 JavaScriptScanner::JavaScriptScanner(UnicodeCache* scanner_contants) |
118 : Scanner(scanner_contants) { } | 100 : Scanner(scanner_contants) { } |
119 | 101 |
120 | 102 |
121 Token::Value JavaScriptScanner::Next() { | 103 Token::Value JavaScriptScanner::Next() { |
122 current_ = next_; | 104 current_ = next_; |
123 has_line_terminator_before_next_ = false; | 105 has_line_terminator_before_next_ = false; |
124 Scan(); | 106 Scan(); |
125 return current_.token; | 107 return current_.token; |
126 } | 108 } |
127 | 109 |
128 | 110 |
129 static inline bool IsByteOrderMark(uc32 c) { | 111 static inline bool IsByteOrderMark(uc32 c) { |
130 // The Unicode value U+FFFE is guaranteed never to be assigned as a | 112 // The Unicode value U+FFFE is guaranteed never to be assigned as a |
131 // Unicode character; this implies that in a Unicode context the | 113 // Unicode character; this implies that in a Unicode context the |
132 // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF | 114 // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF |
133 // character expressed in little-endian byte order (since it could | 115 // character expressed in little-endian byte order (since it could |
134 // not be a U+FFFE character expressed in big-endian byte | 116 // not be a U+FFFE character expressed in big-endian byte |
135 // order). Nevertheless, we check for it to be compatible with | 117 // order). Nevertheless, we check for it to be compatible with |
136 // Spidermonkey. | 118 // Spidermonkey. |
137 return c == 0xFEFF || c == 0xFFFE; | 119 return c == 0xFEFF || c == 0xFFFE; |
138 } | 120 } |
139 | 121 |
140 | 122 |
141 bool JavaScriptScanner::SkipWhiteSpace() { | 123 bool JavaScriptScanner::SkipWhiteSpace() { |
142 int start_position = source_pos(); | 124 int start_position = source_pos(); |
143 | 125 |
144 while (true) { | 126 while (true) { |
145 // We treat byte-order marks (BOMs) as whitespace for better | 127 // We treat byte-order marks (BOMs) as whitespace for better |
146 // compatibility with Spidermonkey and other JavaScript engines. | 128 // compatibility with Spidermonkey and other JavaScript engines. |
147 while (scanner_constants_->IsWhiteSpace(c0_) || IsByteOrderMark(c0_)) { | 129 while (unicode_cache_->IsWhiteSpace(c0_) || IsByteOrderMark(c0_)) { |
148 // IsWhiteSpace() includes line terminators! | 130 // IsWhiteSpace() includes line terminators! |
149 if (scanner_constants_->IsLineTerminator(c0_)) { | 131 if (unicode_cache_->IsLineTerminator(c0_)) { |
150 // Ignore line terminators, but remember them. This is necessary | 132 // Ignore line terminators, but remember them. This is necessary |
151 // for automatic semicolon insertion. | 133 // for automatic semicolon insertion. |
152 has_line_terminator_before_next_ = true; | 134 has_line_terminator_before_next_ = true; |
153 } | 135 } |
154 Advance(); | 136 Advance(); |
155 } | 137 } |
156 | 138 |
157 // If there is an HTML comment end '-->' at the beginning of a | 139 // If there is an HTML comment end '-->' at the beginning of a |
158 // line (with only whitespace in front of it), we treat the rest | 140 // line (with only whitespace in front of it), we treat the rest |
159 // of the line as a comment. This is in line with the way | 141 // of the line as a comment. This is in line with the way |
(...skipping 19 matching lines...) Expand all Loading... |
179 | 161 |
180 | 162 |
181 Token::Value JavaScriptScanner::SkipSingleLineComment() { | 163 Token::Value JavaScriptScanner::SkipSingleLineComment() { |
182 Advance(); | 164 Advance(); |
183 | 165 |
184 // The line terminator at the end of the line is not considered | 166 // The line terminator at the end of the line is not considered |
185 // to be part of the single-line comment; it is recognized | 167 // to be part of the single-line comment; it is recognized |
186 // separately by the lexical grammar and becomes part of the | 168 // separately by the lexical grammar and becomes part of the |
187 // stream of input elements for the syntactic grammar (see | 169 // stream of input elements for the syntactic grammar (see |
188 // ECMA-262, section 7.4, page 12). | 170 // ECMA-262, section 7.4, page 12). |
189 while (c0_ >= 0 && !scanner_constants_->IsLineTerminator(c0_)) { | 171 while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) { |
190 Advance(); | 172 Advance(); |
191 } | 173 } |
192 | 174 |
193 return Token::WHITESPACE; | 175 return Token::WHITESPACE; |
194 } | 176 } |
195 | 177 |
196 | 178 |
197 Token::Value JavaScriptScanner::SkipMultiLineComment() { | 179 Token::Value JavaScriptScanner::SkipMultiLineComment() { |
198 ASSERT(c0_ == '*'); | 180 ASSERT(c0_ == '*'); |
199 Advance(); | 181 Advance(); |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 | 426 |
445 case '?': | 427 case '?': |
446 token = Select(Token::CONDITIONAL); | 428 token = Select(Token::CONDITIONAL); |
447 break; | 429 break; |
448 | 430 |
449 case '~': | 431 case '~': |
450 token = Select(Token::BIT_NOT); | 432 token = Select(Token::BIT_NOT); |
451 break; | 433 break; |
452 | 434 |
453 default: | 435 default: |
454 if (scanner_constants_->IsIdentifierStart(c0_)) { | 436 if (unicode_cache_->IsIdentifierStart(c0_)) { |
455 token = ScanIdentifierOrKeyword(); | 437 token = ScanIdentifierOrKeyword(); |
456 } else if (IsDecimalDigit(c0_)) { | 438 } else if (IsDecimalDigit(c0_)) { |
457 token = ScanNumber(false); | 439 token = ScanNumber(false); |
458 } else if (SkipWhiteSpace()) { | 440 } else if (SkipWhiteSpace()) { |
459 token = Token::WHITESPACE; | 441 token = Token::WHITESPACE; |
460 } else if (c0_ < 0) { | 442 } else if (c0_ < 0) { |
461 token = Token::EOS; | 443 token = Token::EOS; |
462 } else { | 444 } else { |
463 token = Select(Token::ILLEGAL); | 445 token = Select(Token::ILLEGAL); |
464 } | 446 } |
(...skipping 27 matching lines...) Expand all Loading... |
492 } | 474 } |
493 Scan(); | 475 Scan(); |
494 } | 476 } |
495 | 477 |
496 | 478 |
497 void JavaScriptScanner::ScanEscape() { | 479 void JavaScriptScanner::ScanEscape() { |
498 uc32 c = c0_; | 480 uc32 c = c0_; |
499 Advance(); | 481 Advance(); |
500 | 482 |
501 // Skip escaped newlines. | 483 // Skip escaped newlines. |
502 if (scanner_constants_->IsLineTerminator(c)) { | 484 if (unicode_cache_->IsLineTerminator(c)) { |
503 // Allow CR+LF newlines in multiline string literals. | 485 // Allow CR+LF newlines in multiline string literals. |
504 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance(); | 486 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance(); |
505 // Allow LF+CR newlines in multiline string literals. | 487 // Allow LF+CR newlines in multiline string literals. |
506 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance(); | 488 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance(); |
507 return; | 489 return; |
508 } | 490 } |
509 | 491 |
510 switch (c) { | 492 switch (c) { |
511 case '\'': // fall through | 493 case '\'': // fall through |
512 case '"' : // fall through | 494 case '"' : // fall through |
(...skipping 22 matching lines...) Expand all Loading... |
535 AddLiteralChar(c); | 517 AddLiteralChar(c); |
536 } | 518 } |
537 | 519 |
538 | 520 |
539 Token::Value JavaScriptScanner::ScanString() { | 521 Token::Value JavaScriptScanner::ScanString() { |
540 uc32 quote = c0_; | 522 uc32 quote = c0_; |
541 Advance(); // consume quote | 523 Advance(); // consume quote |
542 | 524 |
543 LiteralScope literal(this); | 525 LiteralScope literal(this); |
544 while (c0_ != quote && c0_ >= 0 | 526 while (c0_ != quote && c0_ >= 0 |
545 && !scanner_constants_->IsLineTerminator(c0_)) { | 527 && !unicode_cache_->IsLineTerminator(c0_)) { |
546 uc32 c = c0_; | 528 uc32 c = c0_; |
547 Advance(); | 529 Advance(); |
548 if (c == '\\') { | 530 if (c == '\\') { |
549 if (c0_ < 0) return Token::ILLEGAL; | 531 if (c0_ < 0) return Token::ILLEGAL; |
550 ScanEscape(); | 532 ScanEscape(); |
551 } else { | 533 } else { |
552 AddLiteralChar(c); | 534 AddLiteralChar(c); |
553 } | 535 } |
554 } | 536 } |
555 if (c0_ != quote) return Token::ILLEGAL; | 537 if (c0_ != quote) return Token::ILLEGAL; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 // we must have at least one decimal digit after 'e'/'E' | 616 // we must have at least one decimal digit after 'e'/'E' |
635 return Token::ILLEGAL; | 617 return Token::ILLEGAL; |
636 } | 618 } |
637 ScanDecimalDigits(); | 619 ScanDecimalDigits(); |
638 } | 620 } |
639 | 621 |
640 // The source character immediately following a numeric literal must | 622 // The source character immediately following a numeric literal must |
641 // not be an identifier start or a decimal digit; see ECMA-262 | 623 // not be an identifier start or a decimal digit; see ECMA-262 |
642 // section 7.8.3, page 17 (note that we read only one decimal digit | 624 // section 7.8.3, page 17 (note that we read only one decimal digit |
643 // if the value is 0). | 625 // if the value is 0). |
644 if (IsDecimalDigit(c0_) || scanner_constants_->IsIdentifierStart(c0_)) | 626 if (IsDecimalDigit(c0_) || unicode_cache_->IsIdentifierStart(c0_)) |
645 return Token::ILLEGAL; | 627 return Token::ILLEGAL; |
646 | 628 |
647 literal.Complete(); | 629 literal.Complete(); |
648 | 630 |
649 return Token::NUMBER; | 631 return Token::NUMBER; |
650 } | 632 } |
651 | 633 |
652 | 634 |
653 uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() { | 635 uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() { |
654 Advance(); | 636 Advance(); |
655 if (c0_ != 'u') return unibrow::Utf8::kBadChar; | 637 if (c0_ != 'u') return unibrow::Utf8::kBadChar; |
656 Advance(); | 638 Advance(); |
657 uc32 c = ScanHexEscape('u', 4); | 639 uc32 c = ScanHexEscape('u', 4); |
658 // We do not allow a unicode escape sequence to start another | 640 // We do not allow a unicode escape sequence to start another |
659 // unicode escape sequence. | 641 // unicode escape sequence. |
660 if (c == '\\') return unibrow::Utf8::kBadChar; | 642 if (c == '\\') return unibrow::Utf8::kBadChar; |
661 return c; | 643 return c; |
662 } | 644 } |
663 | 645 |
664 | 646 |
665 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() { | 647 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() { |
666 ASSERT(scanner_constants_->IsIdentifierStart(c0_)); | 648 ASSERT(unicode_cache_->IsIdentifierStart(c0_)); |
667 LiteralScope literal(this); | 649 LiteralScope literal(this); |
668 KeywordMatcher keyword_match; | 650 KeywordMatcher keyword_match; |
669 // Scan identifier start character. | 651 // Scan identifier start character. |
670 if (c0_ == '\\') { | 652 if (c0_ == '\\') { |
671 uc32 c = ScanIdentifierUnicodeEscape(); | 653 uc32 c = ScanIdentifierUnicodeEscape(); |
672 // Only allow legal identifier start characters. | 654 // Only allow legal identifier start characters. |
673 if (!scanner_constants_->IsIdentifierStart(c)) return Token::ILLEGAL; | 655 if (!unicode_cache_->IsIdentifierStart(c)) return Token::ILLEGAL; |
674 AddLiteralChar(c); | 656 AddLiteralChar(c); |
675 return ScanIdentifierSuffix(&literal); | 657 return ScanIdentifierSuffix(&literal); |
676 } | 658 } |
677 | 659 |
678 uc32 first_char = c0_; | 660 uc32 first_char = c0_; |
679 Advance(); | 661 Advance(); |
680 AddLiteralChar(first_char); | 662 AddLiteralChar(first_char); |
681 if (!keyword_match.AddChar(first_char)) { | 663 if (!keyword_match.AddChar(first_char)) { |
682 return ScanIdentifierSuffix(&literal); | 664 return ScanIdentifierSuffix(&literal); |
683 } | 665 } |
684 | 666 |
685 // Scan the rest of the identifier characters. | 667 // Scan the rest of the identifier characters. |
686 while (scanner_constants_->IsIdentifierPart(c0_)) { | 668 while (unicode_cache_->IsIdentifierPart(c0_)) { |
687 if (c0_ != '\\') { | 669 if (c0_ != '\\') { |
688 uc32 next_char = c0_; | 670 uc32 next_char = c0_; |
689 Advance(); | 671 Advance(); |
690 AddLiteralChar(next_char); | 672 AddLiteralChar(next_char); |
691 if (keyword_match.AddChar(next_char)) continue; | 673 if (keyword_match.AddChar(next_char)) continue; |
692 } | 674 } |
693 // Fallthrough if no loner able to complete keyword. | 675 // Fallthrough if no loner able to complete keyword. |
694 return ScanIdentifierSuffix(&literal); | 676 return ScanIdentifierSuffix(&literal); |
695 } | 677 } |
696 literal.Complete(); | 678 literal.Complete(); |
697 | 679 |
698 return keyword_match.token(); | 680 return keyword_match.token(); |
699 } | 681 } |
700 | 682 |
701 | 683 |
702 Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) { | 684 Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) { |
703 // Scan the rest of the identifier characters. | 685 // Scan the rest of the identifier characters. |
704 while (scanner_constants_->IsIdentifierPart(c0_)) { | 686 while (unicode_cache_->IsIdentifierPart(c0_)) { |
705 if (c0_ == '\\') { | 687 if (c0_ == '\\') { |
706 uc32 c = ScanIdentifierUnicodeEscape(); | 688 uc32 c = ScanIdentifierUnicodeEscape(); |
707 // Only allow legal identifier part characters. | 689 // Only allow legal identifier part characters. |
708 if (!scanner_constants_->IsIdentifierPart(c)) return Token::ILLEGAL; | 690 if (!unicode_cache_->IsIdentifierPart(c)) return Token::ILLEGAL; |
709 AddLiteralChar(c); | 691 AddLiteralChar(c); |
710 } else { | 692 } else { |
711 AddLiteralChar(c0_); | 693 AddLiteralChar(c0_); |
712 Advance(); | 694 Advance(); |
713 } | 695 } |
714 } | 696 } |
715 literal->Complete(); | 697 literal->Complete(); |
716 | 698 |
717 return Token::IDENTIFIER; | 699 return Token::IDENTIFIER; |
718 } | 700 } |
719 | 701 |
720 | 702 |
721 bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) { | 703 bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) { |
722 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags | 704 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags |
723 bool in_character_class = false; | 705 bool in_character_class = false; |
724 | 706 |
725 // Previous token is either '/' or '/=', in the second case, the | 707 // Previous token is either '/' or '/=', in the second case, the |
726 // pattern starts at =. | 708 // pattern starts at =. |
727 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); | 709 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); |
728 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); | 710 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); |
729 | 711 |
730 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, | 712 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, |
731 // the scanner should pass uninterpreted bodies to the RegExp | 713 // the scanner should pass uninterpreted bodies to the RegExp |
732 // constructor. | 714 // constructor. |
733 LiteralScope literal(this); | 715 LiteralScope literal(this); |
734 if (seen_equal) | 716 if (seen_equal) |
735 AddLiteralChar('='); | 717 AddLiteralChar('='); |
736 | 718 |
737 while (c0_ != '/' || in_character_class) { | 719 while (c0_ != '/' || in_character_class) { |
738 if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false; | 720 if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false; |
739 if (c0_ == '\\') { // Escape sequence. | 721 if (c0_ == '\\') { // Escape sequence. |
740 AddLiteralCharAdvance(); | 722 AddLiteralCharAdvance(); |
741 if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false; | 723 if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false; |
742 AddLiteralCharAdvance(); | 724 AddLiteralCharAdvance(); |
743 // If the escape allows more characters, i.e., \x??, \u????, or \c?, | 725 // If the escape allows more characters, i.e., \x??, \u????, or \c?, |
744 // only "safe" characters are allowed (letters, digits, underscore), | 726 // only "safe" characters are allowed (letters, digits, underscore), |
745 // otherwise the escape isn't valid and the invalid character has | 727 // otherwise the escape isn't valid and the invalid character has |
746 // its normal meaning. I.e., we can just continue scanning without | 728 // its normal meaning. I.e., we can just continue scanning without |
747 // worrying whether the following characters are part of the escape | 729 // worrying whether the following characters are part of the escape |
748 // or not, since any '/', '\\' or '[' is guaranteed to not be part | 730 // or not, since any '/', '\\' or '[' is guaranteed to not be part |
749 // of the escape sequence. | 731 // of the escape sequence. |
750 } else { // Unescaped character. | 732 } else { // Unescaped character. |
751 if (c0_ == '[') in_character_class = true; | 733 if (c0_ == '[') in_character_class = true; |
752 if (c0_ == ']') in_character_class = false; | 734 if (c0_ == ']') in_character_class = false; |
753 AddLiteralCharAdvance(); | 735 AddLiteralCharAdvance(); |
754 } | 736 } |
755 } | 737 } |
756 Advance(); // consume '/' | 738 Advance(); // consume '/' |
757 | 739 |
758 literal.Complete(); | 740 literal.Complete(); |
759 | 741 |
760 return true; | 742 return true; |
761 } | 743 } |
762 | 744 |
763 | 745 |
764 bool JavaScriptScanner::ScanRegExpFlags() { | 746 bool JavaScriptScanner::ScanRegExpFlags() { |
765 // Scan regular expression flags. | 747 // Scan regular expression flags. |
766 LiteralScope literal(this); | 748 LiteralScope literal(this); |
767 while (scanner_constants_->IsIdentifierPart(c0_)) { | 749 while (unicode_cache_->IsIdentifierPart(c0_)) { |
768 if (c0_ == '\\') { | 750 if (c0_ == '\\') { |
769 uc32 c = ScanIdentifierUnicodeEscape(); | 751 uc32 c = ScanIdentifierUnicodeEscape(); |
770 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { | 752 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { |
771 // We allow any escaped character, unlike the restriction on | 753 // We allow any escaped character, unlike the restriction on |
772 // IdentifierPart when it is used to build an IdentifierName. | 754 // IdentifierPart when it is used to build an IdentifierName. |
773 AddLiteralChar(c); | 755 AddLiteralChar(c); |
774 continue; | 756 continue; |
775 } | 757 } |
776 } | 758 } |
777 AddLiteralCharAdvance(); | 759 AddLiteralCharAdvance(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; | 937 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; |
956 break; | 938 break; |
957 case UNMATCHABLE: | 939 case UNMATCHABLE: |
958 break; | 940 break; |
959 } | 941 } |
960 // On fallthrough, it's a failure. | 942 // On fallthrough, it's a failure. |
961 state_ = UNMATCHABLE; | 943 state_ = UNMATCHABLE; |
962 } | 944 } |
963 | 945 |
964 } } // namespace v8::internal | 946 } } // namespace v8::internal |
OLD | NEW |