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

Side by Side Diff: src/scanner.cc

Issue 663683006: Implement ES6 Template Literals (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove kTemplateLiteral bailout-reason Created 6 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 | Annotate | Revision Log
OLDNEW
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 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 397 }
398 PushBack('!'); // undo Advance() 398 PushBack('!'); // undo Advance()
399 DCHECK(c0_ == '!'); 399 DCHECK(c0_ == '!');
400 return Token::LT; 400 return Token::LT;
401 } 401 }
402 402
403 403
404 void Scanner::Scan() { 404 void Scanner::Scan() {
405 next_.literal_chars = NULL; 405 next_.literal_chars = NULL;
406 Token::Value token; 406 Token::Value token;
407
407 do { 408 do {
408 // Remember the position of the next token 409 // Remember the position of the next token
409 next_.location.beg_pos = source_pos(); 410 next_.location.beg_pos = source_pos();
410 411
411 switch (c0_) { 412 switch (c0_) {
412 case ' ': 413 case ' ':
413 case '\t': 414 case '\t':
414 Advance(); 415 Advance();
415 token = Token::WHITESPACE; 416 token = Token::WHITESPACE;
416 break; 417 break;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 break; 620 break;
620 621
621 case '?': 622 case '?':
622 token = Select(Token::CONDITIONAL); 623 token = Select(Token::CONDITIONAL);
623 break; 624 break;
624 625
625 case '~': 626 case '~':
626 token = Select(Token::BIT_NOT); 627 token = Select(Token::BIT_NOT);
627 break; 628 break;
628 629
630 case '`':
631 if (HarmonyTemplates()) {
632 token = ScanTemplateSpan();
633 break;
634 }
635
629 default: 636 default:
630 if (c0_ < 0) { 637 if (c0_ < 0) {
631 token = Token::EOS; 638 token = Token::EOS;
632 } else if (unicode_cache_->IsIdentifierStart(c0_)) { 639 } else if (unicode_cache_->IsIdentifierStart(c0_)) {
633 token = ScanIdentifierOrKeyword(); 640 token = ScanIdentifierOrKeyword();
634 } else if (IsDecimalDigit(c0_)) { 641 } else if (IsDecimalDigit(c0_)) {
635 token = ScanNumber(false); 642 token = ScanNumber(false);
636 } else if (SkipWhiteSpace()) { 643 } else if (SkipWhiteSpace()) {
637 token = Token::WHITESPACE; 644 token = Token::WHITESPACE;
638 } else { 645 } else {
(...skipping 27 matching lines...) Expand all
666 // whether there was a line terminator in the part we skip. 673 // whether there was a line terminator in the part we skip.
667 has_line_terminator_before_next_ = false; 674 has_line_terminator_before_next_ = false;
668 has_multiline_comment_before_next_ = false; 675 has_multiline_comment_before_next_ = false;
669 } 676 }
670 Scan(); 677 Scan();
671 } 678 }
672 679
673 680
674 bool Scanner::ScanEscape() { 681 bool Scanner::ScanEscape() {
675 uc32 c = c0_; 682 uc32 c = c0_;
683 bool singleCharEscape = true;
arv (Not doing code reviews) 2014/11/11 17:15:15 This is no longer used
676 Advance(); 684 Advance();
677 685
678 // Skip escaped newlines. 686 // Skip escaped newlines.
679 if (c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) { 687 if (c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) {
680 // Allow CR+LF newlines in multiline string literals. 688 // Allow CR+LF newlines in multiline string literals.
681 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance(); 689 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
682 // Allow LF+CR newlines in multiline string literals. 690 // Allow LF+CR newlines in multiline string literals.
683 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance(); 691 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance();
684 return true; 692 return true;
685 } 693 }
686 694
687 switch (c) { 695 switch (c) {
688 case '\'': // fall through 696 case '\'': // fall through
689 case '"' : // fall through 697 case '"' : // fall through
690 case '\\': break; 698 case '\\': break;
691 case 'b' : c = '\b'; break; 699 case 'b' : c = '\b'; break;
692 case 'f' : c = '\f'; break; 700 case 'f' : c = '\f'; break;
693 case 'n' : c = '\n'; break; 701 case 'n' : c = '\n'; break;
694 case 'r' : c = '\r'; break; 702 case 'r' : c = '\r'; break;
695 case 't' : c = '\t'; break; 703 case 't' : c = '\t'; break;
696 case 'u' : { 704 case 'u' : {
705 singleCharEscape = false;
697 c = ScanHexNumber(4); 706 c = ScanHexNumber(4);
698 if (c < 0) return false; 707 if (c < 0) return false;
699 break; 708 break;
700 } 709 }
701 case 'v' : c = '\v'; break; 710 case 'v' : c = '\v'; break;
702 case 'x' : { 711 case 'x' : {
712 singleCharEscape = false;
703 c = ScanHexNumber(2); 713 c = ScanHexNumber(2);
704 if (c < 0) return false; 714 if (c < 0) return false;
705 break; 715 break;
706 } 716 }
707 case '0' : // fall through 717 case '0' : // fall through
708 case '1' : // fall through 718 case '1' : // fall through
709 case '2' : // fall through 719 case '2' : // fall through
710 case '3' : // fall through 720 case '3' : // fall through
711 case '4' : // fall through 721 case '4' : // fall through
712 case '5' : // fall through 722 case '5' : // fall through
713 case '6' : // fall through 723 case '6' : // fall through
714 case '7' : c = ScanOctalEscape(c, 2); break; 724 case '7':
725 singleCharEscape = false;
726 c = ScanOctalEscape(c, 2);
727 break;
715 } 728 }
716 729
717 // According to ECMA-262, section 7.8.4, characters not covered by the 730 // According to ECMA-262, section 7.8.4, characters not covered by the
718 // above cases should be illegal, but they are commonly handled as 731 // above cases should be illegal, but they are commonly handled as
719 // non-escaped characters by JS VMs. 732 // non-escaped characters by JS VMs.
720 AddLiteralChar(c); 733 AddLiteralChar(c);
721 return true; 734 return true;
722 } 735 }
723 736
724 737
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 } 776 }
764 } 777 }
765 if (c0_ != quote) return Token::ILLEGAL; 778 if (c0_ != quote) return Token::ILLEGAL;
766 literal.Complete(); 779 literal.Complete();
767 780
768 Advance(); // consume quote 781 Advance(); // consume quote
769 return Token::STRING; 782 return Token::STRING;
770 } 783 }
771 784
772 785
786 Token::Value Scanner::ScanTemplateSpan() {
787 // When scanning a TemplateSpan, we are looking for the following construct:
788 // TEMPLATE_SPAN ::
789 // ` LiteralChars* ${
790 // | } LiteralChars* ${
791 //
792 // TEMPLATE_TAIL ::
793 // ` LiteralChars* `
794 // | } LiteralChar* `
795 //
796 // A TEMPLATE_SPAN should always be followed by an Expression, while a
797 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
798 // followed by an Expression.
799 //
800
801 if (next_.token == Token::RBRACE) {
802 // After parsing an Expression, the source position is incorrect due to
803 // having scanned the brace. Push the RBRACE back into the stream.
804 PushBack('}');
805 }
806
807 next_.location.beg_pos = source_pos();
808 Token::Value result = Token::ILLEGAL;
809 DCHECK(c0_ == '`' || c0_ == '}');
810 Advance(); // Consume ` or }
811
812 LiteralScope literal(this);
813 while (true) {
814 uc32 c = c0_;
815 Advance();
816 if (c == '`') {
817 result = Token::TEMPLATE_TAIL;
818 break;
819 } else if (c == '$' && c0_ == '{') {
820 Advance(); // Consume '{'
821 result = Token::TEMPLATE_SPAN;
822 break;
823 } else if (c == '\\') {
824 if (unicode_cache_->IsLineTerminator(c0_)) {
825 // The TV of LineContinuation :: \ LineTerminatorSequence is the empty
826 // code unit sequence.
827 do {
828 uc32 lastChar = c0_;
829 Advance();
830 if (lastChar == '\r' && c0_ == '\n') Advance();
831 } while (unicode_cache_->IsLineTerminator(c0_));
832 } else if (c0_ == '0') {
833 Advance();
834 AddLiteralChar('0');
835 } else {
836 ScanEscape();
837 }
838 } else if (c < 0) {
839 // Unterminated template literal
840 PushBack(c);
841 break;
842 } else {
843 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
844 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
845 // consisting of the CV 0x000A.
846 if (c == '\r') {
847 if (c0_ == '\n') Advance();
848 c = '\n';
849 }
850 AddLiteralChar(c);
851 }
852 }
853 literal.Complete();
854 next_.location.end_pos = source_pos();
855 next_.token = result;
856 return result;
857 }
858
859
773 void Scanner::ScanDecimalDigits() { 860 void Scanner::ScanDecimalDigits() {
774 while (IsDecimalDigit(c0_)) 861 while (IsDecimalDigit(c0_))
775 AddLiteralCharAdvance(); 862 AddLiteralCharAdvance();
776 } 863 }
777 864
778 865
779 Token::Value Scanner::ScanNumber(bool seen_period) { 866 Token::Value Scanner::ScanNumber(bool seen_period) {
780 DCHECK(IsDecimalDigit(c0_)); // the first digit of the number or the fraction 867 DCHECK(IsDecimalDigit(c0_)); // the first digit of the number or the fraction
781 868
782 enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL; 869 enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 } 1413 }
1327 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u)); 1414 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u));
1328 } 1415 }
1329 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f)); 1416 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f));
1330 1417
1331 backing_store_.AddBlock(bytes); 1418 backing_store_.AddBlock(bytes);
1332 return backing_store_.EndSequence().start(); 1419 return backing_store_.EndSequence().start();
1333 } 1420 }
1334 1421
1335 } } // namespace v8::internal 1422 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698