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 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 break; | 619 break; |
620 | 620 |
621 case '?': | 621 case '?': |
622 token = Select(Token::CONDITIONAL); | 622 token = Select(Token::CONDITIONAL); |
623 break; | 623 break; |
624 | 624 |
625 case '~': | 625 case '~': |
626 token = Select(Token::BIT_NOT); | 626 token = Select(Token::BIT_NOT); |
627 break; | 627 break; |
628 | 628 |
| 629 case '`': |
| 630 if (HarmonyTemplates()) { |
| 631 token = ScanTemplateSpan(); |
| 632 break; |
| 633 } |
| 634 |
629 default: | 635 default: |
630 if (c0_ < 0) { | 636 if (c0_ < 0) { |
631 token = Token::EOS; | 637 token = Token::EOS; |
632 } else if (unicode_cache_->IsIdentifierStart(c0_)) { | 638 } else if (unicode_cache_->IsIdentifierStart(c0_)) { |
633 token = ScanIdentifierOrKeyword(); | 639 token = ScanIdentifierOrKeyword(); |
634 } else if (IsDecimalDigit(c0_)) { | 640 } else if (IsDecimalDigit(c0_)) { |
635 token = ScanNumber(false); | 641 token = ScanNumber(false); |
636 } else if (SkipWhiteSpace()) { | 642 } else if (SkipWhiteSpace()) { |
637 token = Token::WHITESPACE; | 643 token = Token::WHITESPACE; |
638 } else { | 644 } else { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 } | 769 } |
764 } | 770 } |
765 if (c0_ != quote) return Token::ILLEGAL; | 771 if (c0_ != quote) return Token::ILLEGAL; |
766 literal.Complete(); | 772 literal.Complete(); |
767 | 773 |
768 Advance(); // consume quote | 774 Advance(); // consume quote |
769 return Token::STRING; | 775 return Token::STRING; |
770 } | 776 } |
771 | 777 |
772 | 778 |
| 779 Token::Value Scanner::ScanTemplateSpan() { |
| 780 // When scanning a TemplateSpan, we are looking for the following construct: |
| 781 // TEMPLATE_SPAN :: |
| 782 // ` LiteralChars* ${ |
| 783 // | } LiteralChars* ${ |
| 784 // |
| 785 // TEMPLATE_TAIL :: |
| 786 // ` LiteralChars* ` |
| 787 // | } LiteralChar* ` |
| 788 // |
| 789 // A TEMPLATE_SPAN should always be followed by an Expression, while a |
| 790 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be |
| 791 // followed by an Expression. |
| 792 // |
| 793 |
| 794 if (next_.token == Token::RBRACE) { |
| 795 // After parsing an Expression, the source position is incorrect due to |
| 796 // having scanned the brace. Push the RBRACE back into the stream. |
| 797 PushBack('}'); |
| 798 } |
| 799 |
| 800 next_.location.beg_pos = source_pos(); |
| 801 Token::Value result = Token::ILLEGAL; |
| 802 DCHECK(c0_ == '`' || c0_ == '}'); |
| 803 Advance(); // Consume ` or } |
| 804 |
| 805 LiteralScope literal(this); |
| 806 while (true) { |
| 807 uc32 c = c0_; |
| 808 Advance(); |
| 809 if (c == '`') { |
| 810 result = Token::TEMPLATE_TAIL; |
| 811 break; |
| 812 } else if (c == '$' && c0_ == '{') { |
| 813 Advance(); // Consume '{' |
| 814 result = Token::TEMPLATE_SPAN; |
| 815 break; |
| 816 } else if (c == '\\') { |
| 817 if (unicode_cache_->IsLineTerminator(c0_)) { |
| 818 // The TV of LineContinuation :: \ LineTerminatorSequence is the empty |
| 819 // code unit sequence. |
| 820 uc32 lastChar = c0_; |
| 821 Advance(); |
| 822 if (lastChar == '\r' && c0_ == '\n') Advance(); |
| 823 } else if (c0_ == '0') { |
| 824 Advance(); |
| 825 AddLiteralChar('0'); |
| 826 } else { |
| 827 ScanEscape(); |
| 828 } |
| 829 } else if (c < 0) { |
| 830 // Unterminated template literal |
| 831 PushBack(c); |
| 832 break; |
| 833 } else { |
| 834 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A. |
| 835 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence |
| 836 // consisting of the CV 0x000A. |
| 837 if (c == '\r') { |
| 838 if (c0_ == '\n') Advance(); |
| 839 c = '\n'; |
| 840 } |
| 841 AddLiteralChar(c); |
| 842 } |
| 843 } |
| 844 literal.Complete(); |
| 845 next_.location.end_pos = source_pos(); |
| 846 next_.token = result; |
| 847 return result; |
| 848 } |
| 849 |
| 850 |
773 void Scanner::ScanDecimalDigits() { | 851 void Scanner::ScanDecimalDigits() { |
774 while (IsDecimalDigit(c0_)) | 852 while (IsDecimalDigit(c0_)) |
775 AddLiteralCharAdvance(); | 853 AddLiteralCharAdvance(); |
776 } | 854 } |
777 | 855 |
778 | 856 |
779 Token::Value Scanner::ScanNumber(bool seen_period) { | 857 Token::Value Scanner::ScanNumber(bool seen_period) { |
780 DCHECK(IsDecimalDigit(c0_)); // the first digit of the number or the fraction | 858 DCHECK(IsDecimalDigit(c0_)); // the first digit of the number or the fraction |
781 | 859 |
782 enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL; | 860 enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL; |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 } | 1404 } |
1327 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u)); | 1405 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u)); |
1328 } | 1406 } |
1329 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f)); | 1407 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f)); |
1330 | 1408 |
1331 backing_store_.AddBlock(bytes); | 1409 backing_store_.AddBlock(bytes); |
1332 return backing_store_.EndSequence().start(); | 1410 return backing_store_.EndSequence().start(); |
1333 } | 1411 } |
1334 | 1412 |
1335 } } // namespace v8::internal | 1413 } } // namespace v8::internal |
OLD | NEW |