Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Features shared by parsing and pre-parsing scanners. | 5 // Features shared by parsing and pre-parsing scanners. |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <cmath> | 9 #include <cmath> |
| 10 | 10 |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 690 // This function is only called to seek to the location | 690 // This function is only called to seek to the location |
| 691 // of the end of a function (at the "}" token). It doesn't matter | 691 // of the end of a function (at the "}" token). It doesn't matter |
| 692 // whether there was a line terminator in the part we skip. | 692 // whether there was a line terminator in the part we skip. |
| 693 has_line_terminator_before_next_ = false; | 693 has_line_terminator_before_next_ = false; |
| 694 has_multiline_comment_before_next_ = false; | 694 has_multiline_comment_before_next_ = false; |
| 695 } | 695 } |
| 696 Scan(); | 696 Scan(); |
| 697 } | 697 } |
| 698 | 698 |
| 699 | 699 |
| 700 template <bool capture_raw> | 700 template <bool capture_raw, bool in_template_literal> |
| 701 bool Scanner::ScanEscape() { | 701 bool Scanner::ScanEscape() { |
| 702 uc32 c = c0_; | 702 uc32 c = c0_; |
| 703 Advance<capture_raw>(); | 703 Advance<capture_raw>(); |
| 704 | 704 |
| 705 // Skip escaped newlines. | 705 // Skip escaped newlines. |
| 706 if (c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) { | 706 if (!in_template_literal && c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) { |
| 707 // Allow CR+LF newlines in multiline string literals. | 707 // Allow CR+LF newlines in multiline string literals. |
| 708 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>(); | 708 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>(); |
| 709 // Allow LF+CR newlines in multiline string literals. | 709 // Allow LF+CR newlines in multiline string literals. |
| 710 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance<capture_raw>(); | 710 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance<capture_raw>(); |
| 711 return true; | 711 return true; |
| 712 } | 712 } |
| 713 | 713 |
| 714 switch (c) { | 714 switch (c) { |
| 715 case '\'': // fall through | 715 case '\'': // fall through |
| 716 case '"' : // fall through | 716 case '"' : // fall through |
| 717 case '\\': break; | 717 case '\\': break; |
| 718 case 'b' : c = '\b'; break; | 718 case 'b' : c = '\b'; break; |
| 719 case 'f' : c = '\f'; break; | 719 case 'f' : c = '\f'; break; |
| 720 case 'n' : c = '\n'; break; | 720 case 'n' : c = '\n'; break; |
| 721 case 'r' : c = '\r'; break; | 721 case 'r' : c = '\r'; break; |
| 722 case 't' : c = '\t'; break; | 722 case 't' : c = '\t'; break; |
| 723 case 'u' : { | 723 case 'u' : { |
| 724 c = ScanUnicodeEscape<capture_raw>(); | 724 c = ScanUnicodeEscape<capture_raw>(); |
| 725 if (c < 0) return false; | 725 if (c < 0) return false; |
| 726 break; | 726 break; |
| 727 } | 727 } |
| 728 case 'v' : c = '\v'; break; | 728 case 'v' : c = '\v'; break; |
| 729 case 'x' : { | 729 case 'x' : { |
| 730 c = ScanHexNumber<capture_raw>(2); | 730 c = ScanHexNumber<capture_raw>(2); |
| 731 if (c < 0) return false; | 731 if (c < 0) return false; |
| 732 break; | 732 break; |
| 733 } | 733 } |
| 734 case '0' : // fall through | 734 case '0': |
| 735 if (in_template_literal) { | |
| 736 // \ 0 DecimalDigit is never allowed in templates. | |
| 737 if (IsDecimalDigit(c0_)) { | |
| 738 Advance<capture_raw>(); | |
| 739 return false; | |
|
caitp (gmail)
2014/12/17 19:35:56
I feel like we should just let ScanOctalEscape do
| |
| 740 } | |
| 741 | |
| 742 // The TV of TemplateCharacter :: \ EscapeSequence is the CV of | |
| 743 // EscapeSequence. | |
| 744 // The CV of EscapeSequence :: 0 is the code unit value 0. | |
| 745 c = 0; | |
| 746 break; | |
| 747 } | |
| 748 // Fall through. | |
| 735 case '1' : // fall through | 749 case '1' : // fall through |
| 736 case '2' : // fall through | 750 case '2' : // fall through |
| 737 case '3' : // fall through | 751 case '3' : // fall through |
| 738 case '4' : // fall through | 752 case '4' : // fall through |
| 739 case '5' : // fall through | 753 case '5' : // fall through |
| 740 case '6' : // fall through | 754 case '6' : // fall through |
| 741 case '7': | 755 case '7': |
| 742 c = ScanOctalEscape<capture_raw>(c, 2); | 756 if (!in_template_literal) { |
| 757 c = ScanOctalEscape<capture_raw>(c, 2); | |
| 758 } | |
| 743 break; | 759 break; |
| 744 } | 760 } |
| 745 | 761 |
| 746 // According to ECMA-262, section 7.8.4, characters not covered by the | 762 // According to ECMA-262, section 7.8.4, characters not covered by the |
| 747 // above cases should be illegal, but they are commonly handled as | 763 // above cases should be illegal, but they are commonly handled as |
| 748 // non-escaped characters by JS VMs. | 764 // non-escaped characters by JS VMs. |
| 749 AddLiteralChar(c); | 765 AddLiteralChar(c); |
| 750 return true; | 766 return true; |
| 751 } | 767 } |
| 752 | 768 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 780 Token::Value Scanner::ScanString() { | 796 Token::Value Scanner::ScanString() { |
| 781 uc32 quote = c0_; | 797 uc32 quote = c0_; |
| 782 Advance(); // consume quote | 798 Advance(); // consume quote |
| 783 | 799 |
| 784 LiteralScope literal(this); | 800 LiteralScope literal(this); |
| 785 while (c0_ != quote && c0_ >= 0 | 801 while (c0_ != quote && c0_ >= 0 |
| 786 && !unicode_cache_->IsLineTerminator(c0_)) { | 802 && !unicode_cache_->IsLineTerminator(c0_)) { |
| 787 uc32 c = c0_; | 803 uc32 c = c0_; |
| 788 Advance(); | 804 Advance(); |
| 789 if (c == '\\') { | 805 if (c == '\\') { |
| 790 if (c0_ < 0 || !ScanEscape<false>()) return Token::ILLEGAL; | 806 if (c0_ < 0 || !ScanEscape<false, false>()) return Token::ILLEGAL; |
| 791 } else { | 807 } else { |
| 792 AddLiteralChar(c); | 808 AddLiteralChar(c); |
| 793 } | 809 } |
| 794 } | 810 } |
| 795 if (c0_ != quote) return Token::ILLEGAL; | 811 if (c0_ != quote) return Token::ILLEGAL; |
| 796 literal.Complete(); | 812 literal.Complete(); |
| 797 | 813 |
| 798 Advance(); // consume quote | 814 Advance(); // consume quote |
| 799 return Token::STRING; | 815 return Token::STRING; |
| 800 } | 816 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 811 // | } LiteralChar* ` | 827 // | } LiteralChar* ` |
| 812 // | 828 // |
| 813 // A TEMPLATE_SPAN should always be followed by an Expression, while a | 829 // A TEMPLATE_SPAN should always be followed by an Expression, while a |
| 814 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be | 830 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be |
| 815 // followed by an Expression. | 831 // followed by an Expression. |
| 816 | 832 |
| 817 Token::Value result = Token::TEMPLATE_SPAN; | 833 Token::Value result = Token::TEMPLATE_SPAN; |
| 818 LiteralScope literal(this); | 834 LiteralScope literal(this); |
| 819 StartRawLiteral(); | 835 StartRawLiteral(); |
| 820 const bool capture_raw = true; | 836 const bool capture_raw = true; |
| 837 const bool in_template_literal = true; | |
| 821 | 838 |
| 822 while (true) { | 839 while (true) { |
| 823 uc32 c = c0_; | 840 uc32 c = c0_; |
| 824 Advance<capture_raw>(); | 841 Advance<capture_raw>(); |
| 825 if (c == '`') { | 842 if (c == '`') { |
| 826 result = Token::TEMPLATE_TAIL; | 843 result = Token::TEMPLATE_TAIL; |
| 827 ReduceRawLiteralLength(1); | 844 ReduceRawLiteralLength(1); |
| 828 break; | 845 break; |
| 829 } else if (c == '$' && c0_ == '{') { | 846 } else if (c == '$' && c0_ == '{') { |
| 830 Advance<capture_raw>(); // Consume '{' | 847 Advance<capture_raw>(); // Consume '{' |
| 831 ReduceRawLiteralLength(2); | 848 ReduceRawLiteralLength(2); |
| 832 break; | 849 break; |
| 833 } else if (c == '\\') { | 850 } else if (c == '\\') { |
| 834 if (unicode_cache_->IsLineTerminator(c0_)) { | 851 if (unicode_cache_->IsLineTerminator(c0_)) { |
| 835 // The TV of LineContinuation :: \ LineTerminatorSequence is the empty | 852 // The TV of LineContinuation :: \ LineTerminatorSequence is the empty |
| 836 // code unit sequence. | 853 // code unit sequence. |
| 837 uc32 lastChar = c0_; | 854 uc32 lastChar = c0_; |
| 838 Advance<capture_raw>(); | 855 Advance<capture_raw>(); |
| 839 if (lastChar == '\r') { | 856 if (lastChar == '\r') { |
| 840 ReduceRawLiteralLength(1); // Remove \r | 857 ReduceRawLiteralLength(1); // Remove \r |
| 841 if (c0_ == '\n') { | 858 if (c0_ == '\n') { |
| 842 Advance<capture_raw>(); // Adds \n | 859 Advance<capture_raw>(); // Adds \n |
| 843 } else { | 860 } else { |
| 844 AddRawLiteralChar('\n'); | 861 AddRawLiteralChar('\n'); |
| 845 } | 862 } |
| 846 } | 863 } |
| 847 } else if (c0_ == '0') { | 864 } else if (!ScanEscape<capture_raw, in_template_literal>()) { |
| 848 Advance<capture_raw>(); | 865 return Token::ILLEGAL; |
| 849 AddLiteralChar('0'); | |
| 850 } else { | |
| 851 ScanEscape<true>(); | |
| 852 } | 866 } |
| 853 } else if (c < 0) { | 867 } else if (c < 0) { |
| 854 // Unterminated template literal | 868 // Unterminated template literal |
| 855 PushBack(c); | 869 PushBack(c); |
| 856 break; | 870 break; |
| 857 } else { | 871 } else { |
| 858 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A. | 872 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A. |
| 859 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence | 873 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence |
| 860 // consisting of the CV 0x000A. | 874 // consisting of the CV 0x000A. |
| 861 if (c == '\r') { | 875 if (c == '\r') { |
| (...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1478 } | 1492 } |
| 1479 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u)); | 1493 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u)); |
| 1480 } | 1494 } |
| 1481 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f)); | 1495 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f)); |
| 1482 | 1496 |
| 1483 backing_store_.AddBlock(bytes); | 1497 backing_store_.AddBlock(bytes); |
| 1484 return backing_store_.EndSequence().start(); | 1498 return backing_store_.EndSequence().start(); |
| 1485 } | 1499 } |
| 1486 | 1500 |
| 1487 } } // namespace v8::internal | 1501 } } // namespace v8::internal |
| OLD | NEW |