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 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 case '?': | 473 case '?': |
474 token = Select(Token::CONDITIONAL); | 474 token = Select(Token::CONDITIONAL); |
475 break; | 475 break; |
476 | 476 |
477 case '~': | 477 case '~': |
478 token = Select(Token::BIT_NOT); | 478 token = Select(Token::BIT_NOT); |
479 break; | 479 break; |
480 | 480 |
481 default: | 481 default: |
482 if (ScannerConstants::kIsIdentifierStart.get(c0_)) { | 482 if (ScannerConstants::kIsIdentifierStart.get(c0_)) { |
483 token = ScanIdentifier(); | 483 token = ScanIdentifierOrKeyword(); |
484 } else if (IsDecimalDigit(c0_)) { | 484 } else if (IsDecimalDigit(c0_)) { |
485 token = ScanNumber(false); | 485 token = ScanNumber(false); |
486 } else if (SkipWhiteSpace()) { | 486 } else if (SkipWhiteSpace()) { |
487 token = Token::WHITESPACE; | 487 token = Token::WHITESPACE; |
488 } else if (c0_ < 0) { | 488 } else if (c0_ < 0) { |
489 token = Token::EOS; | 489 token = Token::EOS; |
490 } else { | 490 } else { |
491 token = Select(Token::ILLEGAL); | 491 token = Select(Token::ILLEGAL); |
492 } | 492 } |
493 break; | 493 break; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 // should be illegal, but they are commonly handled | 552 // should be illegal, but they are commonly handled |
553 // as non-escaped characters by JS VMs. | 553 // as non-escaped characters by JS VMs. |
554 AddLiteralChar(c); | 554 AddLiteralChar(c); |
555 } | 555 } |
556 | 556 |
557 | 557 |
558 Token::Value JavaScriptScanner::ScanString() { | 558 Token::Value JavaScriptScanner::ScanString() { |
559 uc32 quote = c0_; | 559 uc32 quote = c0_; |
560 Advance(); // consume quote | 560 Advance(); // consume quote |
561 | 561 |
562 LiteralScope literal(this); | 562 LiteralScope literal(this, kLiteralString); |
563 while (c0_ != quote && c0_ >= 0 | 563 while (c0_ != quote && c0_ >= 0 |
564 && !ScannerConstants::kIsLineTerminator.get(c0_)) { | 564 && !ScannerConstants::kIsLineTerminator.get(c0_)) { |
565 uc32 c = c0_; | 565 uc32 c = c0_; |
566 Advance(); | 566 Advance(); |
567 if (c == '\\') { | 567 if (c == '\\') { |
568 if (c0_ < 0) return Token::ILLEGAL; | 568 if (c0_ < 0) return Token::ILLEGAL; |
569 ScanEscape(); | 569 ScanEscape(); |
570 } else { | 570 } else { |
571 AddLiteralChar(c); | 571 AddLiteralChar(c); |
572 } | 572 } |
(...skipping 10 matching lines...) Expand all Loading... |
583 while (IsDecimalDigit(c0_)) | 583 while (IsDecimalDigit(c0_)) |
584 AddLiteralCharAdvance(); | 584 AddLiteralCharAdvance(); |
585 } | 585 } |
586 | 586 |
587 | 587 |
588 Token::Value JavaScriptScanner::ScanNumber(bool seen_period) { | 588 Token::Value JavaScriptScanner::ScanNumber(bool seen_period) { |
589 ASSERT(IsDecimalDigit(c0_)); // the first digit of the number or the fraction | 589 ASSERT(IsDecimalDigit(c0_)); // the first digit of the number or the fraction |
590 | 590 |
591 enum { DECIMAL, HEX, OCTAL } kind = DECIMAL; | 591 enum { DECIMAL, HEX, OCTAL } kind = DECIMAL; |
592 | 592 |
593 LiteralScope literal(this); | 593 LiteralScope literal(this, kLiteralNumber); |
594 if (seen_period) { | 594 if (seen_period) { |
595 // we have already seen a decimal point of the float | 595 // we have already seen a decimal point of the float |
596 AddLiteralChar('.'); | 596 AddLiteralChar('.'); |
597 ScanDecimalDigits(); // we know we have at least one digit | 597 ScanDecimalDigits(); // we know we have at least one digit |
598 | 598 |
599 } else { | 599 } else { |
600 // if the first character is '0' we must check for octals and hex | 600 // if the first character is '0' we must check for octals and hex |
601 if (c0_ == '0') { | 601 if (c0_ == '0') { |
602 AddLiteralCharAdvance(); | 602 AddLiteralCharAdvance(); |
603 | 603 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 if (c0_ != 'u') return unibrow::Utf8::kBadChar; | 670 if (c0_ != 'u') return unibrow::Utf8::kBadChar; |
671 Advance(); | 671 Advance(); |
672 uc32 c = ScanHexEscape('u', 4); | 672 uc32 c = ScanHexEscape('u', 4); |
673 // We do not allow a unicode escape sequence to start another | 673 // We do not allow a unicode escape sequence to start another |
674 // unicode escape sequence. | 674 // unicode escape sequence. |
675 if (c == '\\') return unibrow::Utf8::kBadChar; | 675 if (c == '\\') return unibrow::Utf8::kBadChar; |
676 return c; | 676 return c; |
677 } | 677 } |
678 | 678 |
679 | 679 |
680 Token::Value JavaScriptScanner::ScanIdentifier() { | 680 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() { |
681 ASSERT(ScannerConstants::kIsIdentifierStart.get(c0_)); | 681 ASSERT(ScannerConstants::kIsIdentifierStart.get(c0_)); |
682 | 682 LiteralScope literal(this, kLiteralIdentifier); |
683 LiteralScope literal(this); | |
684 KeywordMatcher keyword_match; | 683 KeywordMatcher keyword_match; |
685 | |
686 // Scan identifier start character. | 684 // Scan identifier start character. |
687 if (c0_ == '\\') { | 685 if (c0_ == '\\') { |
688 uc32 c = ScanIdentifierUnicodeEscape(); | 686 uc32 c = ScanIdentifierUnicodeEscape(); |
689 // Only allow legal identifier start characters. | 687 // Only allow legal identifier start characters. |
690 if (!ScannerConstants::kIsIdentifierStart.get(c)) return Token::ILLEGAL; | 688 if (!ScannerConstants::kIsIdentifierStart.get(c)) return Token::ILLEGAL; |
691 AddLiteralChar(c); | 689 AddLiteralChar(c); |
692 keyword_match.Fail(); | 690 return ScanIdentifierSuffix(&literal); |
693 } else { | 691 } |
694 AddLiteralChar(c0_); | 692 |
695 keyword_match.AddChar(c0_); | 693 uc32 first_char = c0_; |
696 Advance(); | 694 Advance(); |
| 695 AddLiteralChar(first_char); |
| 696 if (!keyword_match.AddChar(first_char)) { |
| 697 return ScanIdentifierSuffix(&literal); |
697 } | 698 } |
698 | 699 |
699 // Scan the rest of the identifier characters. | 700 // Scan the rest of the identifier characters. |
700 while (ScannerConstants::kIsIdentifierPart.get(c0_)) { | 701 while (ScannerConstants::kIsIdentifierPart.get(c0_)) { |
| 702 if (c0_ != '\\') { |
| 703 uc32 next_char = c0_; |
| 704 Advance(); |
| 705 AddLiteralChar(next_char); |
| 706 if (keyword_match.AddChar(next_char)) continue; |
| 707 } |
| 708 // Fallthrough if no loner able to complete keyword. |
| 709 return ScanIdentifierSuffix(&literal); |
| 710 } |
| 711 literal.Complete(); |
| 712 |
| 713 return keyword_match.token(); |
| 714 } |
| 715 |
| 716 |
| 717 Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) { |
| 718 // Scan the rest of the identifier characters. |
| 719 while (ScannerConstants::kIsIdentifierPart.get(c0_)) { |
701 if (c0_ == '\\') { | 720 if (c0_ == '\\') { |
702 uc32 c = ScanIdentifierUnicodeEscape(); | 721 uc32 c = ScanIdentifierUnicodeEscape(); |
703 // Only allow legal identifier part characters. | 722 // Only allow legal identifier part characters. |
704 if (!ScannerConstants::kIsIdentifierPart.get(c)) return Token::ILLEGAL; | 723 if (!ScannerConstants::kIsIdentifierPart.get(c)) return Token::ILLEGAL; |
705 AddLiteralChar(c); | 724 AddLiteralChar(c); |
706 keyword_match.Fail(); | |
707 } else { | 725 } else { |
708 AddLiteralChar(c0_); | 726 AddLiteralChar(c0_); |
709 keyword_match.AddChar(c0_); | |
710 Advance(); | 727 Advance(); |
711 } | 728 } |
712 } | 729 } |
713 literal.Complete(); | 730 literal->Complete(); |
714 | 731 |
715 return keyword_match.token(); | 732 return Token::IDENTIFIER; |
716 } | 733 } |
717 | 734 |
718 | 735 |
719 | |
720 bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) { | 736 bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) { |
721 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags | 737 // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags |
722 bool in_character_class = false; | 738 bool in_character_class = false; |
723 | 739 |
724 // Previous token is either '/' or '/=', in the second case, the | 740 // Previous token is either '/' or '/=', in the second case, the |
725 // pattern starts at =. | 741 // pattern starts at =. |
726 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); | 742 next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1); |
727 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); | 743 next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0); |
728 | 744 |
729 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, | 745 // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5, |
730 // the scanner should pass uninterpreted bodies to the RegExp | 746 // the scanner should pass uninterpreted bodies to the RegExp |
731 // constructor. | 747 // constructor. |
732 LiteralScope literal(this); | 748 LiteralScope literal(this, kLiteralRegExp); |
733 if (seen_equal) | 749 if (seen_equal) |
734 AddLiteralChar('='); | 750 AddLiteralChar('='); |
735 | 751 |
736 while (c0_ != '/' || in_character_class) { | 752 while (c0_ != '/' || in_character_class) { |
737 if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false; | 753 if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false; |
738 if (c0_ == '\\') { // escaped character | 754 if (c0_ == '\\') { // escaped character |
739 AddLiteralCharAdvance(); | 755 AddLiteralCharAdvance(); |
740 if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false; | 756 if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false; |
741 AddLiteralCharAdvance(); | 757 AddLiteralCharAdvance(); |
742 } else { // unescaped character | 758 } else { // unescaped character |
743 if (c0_ == '[') in_character_class = true; | 759 if (c0_ == '[') in_character_class = true; |
744 if (c0_ == ']') in_character_class = false; | 760 if (c0_ == ']') in_character_class = false; |
745 AddLiteralCharAdvance(); | 761 AddLiteralCharAdvance(); |
746 } | 762 } |
747 } | 763 } |
748 Advance(); // consume '/' | 764 Advance(); // consume '/' |
749 | 765 |
750 literal.Complete(); | 766 literal.Complete(); |
751 | 767 |
752 return true; | 768 return true; |
753 } | 769 } |
754 | 770 |
| 771 |
755 bool JavaScriptScanner::ScanRegExpFlags() { | 772 bool JavaScriptScanner::ScanRegExpFlags() { |
756 // Scan regular expression flags. | 773 // Scan regular expression flags. |
757 LiteralScope literal(this); | 774 LiteralScope literal(this, kLiteralRegExpFlags); |
758 while (ScannerConstants::kIsIdentifierPart.get(c0_)) { | 775 while (ScannerConstants::kIsIdentifierPart.get(c0_)) { |
759 if (c0_ == '\\') { | 776 if (c0_ == '\\') { |
760 uc32 c = ScanIdentifierUnicodeEscape(); | 777 uc32 c = ScanIdentifierUnicodeEscape(); |
761 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { | 778 if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) { |
762 // We allow any escaped character, unlike the restriction on | 779 // We allow any escaped character, unlike the restriction on |
763 // IdentifierPart when it is used to build an IdentifierName. | 780 // IdentifierPart when it is used to build an IdentifierName. |
764 AddLiteralChar(c); | 781 AddLiteralChar(c); |
765 continue; | 782 continue; |
766 } | 783 } |
767 } | 784 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return; | 878 if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return; |
862 if (MatchKeywordStart(input, "for", 1, Token::FOR)) return; | 879 if (MatchKeywordStart(input, "for", 1, Token::FOR)) return; |
863 if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return; | 880 if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return; |
864 break; | 881 break; |
865 case I: | 882 case I: |
866 if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return; | 883 if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return; |
867 if (MatchKeyword(input, 'n', IN, Token::IN)) return; | 884 if (MatchKeyword(input, 'n', IN, Token::IN)) return; |
868 break; | 885 break; |
869 case IN: | 886 case IN: |
870 token_ = Token::IDENTIFIER; | 887 token_ = Token::IDENTIFIER; |
871 if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) { | 888 if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) return; |
872 return; | |
873 } | |
874 break; | 889 break; |
875 case N: | 890 case N: |
876 if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return; | 891 if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return; |
877 if (MatchKeywordStart(input, "new", 1, Token::NEW)) return; | 892 if (MatchKeywordStart(input, "new", 1, Token::NEW)) return; |
878 if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return; | 893 if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return; |
879 break; | 894 break; |
880 case T: | 895 case T: |
881 if (MatchState(input, 'h', TH)) return; | 896 if (MatchState(input, 'h', TH)) return; |
882 if (MatchState(input, 'r', TR)) return; | 897 if (MatchState(input, 'r', TR)) return; |
883 if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return; | 898 if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return; |
(...skipping 15 matching lines...) Expand all Loading... |
899 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; | 914 if (MatchKeywordStart(input, "with", 1, Token::WITH)) return; |
900 break; | 915 break; |
901 case UNMATCHABLE: | 916 case UNMATCHABLE: |
902 break; | 917 break; |
903 } | 918 } |
904 // On fallthrough, it's a failure. | 919 // On fallthrough, it's a failure. |
905 state_ = UNMATCHABLE; | 920 state_ = UNMATCHABLE; |
906 } | 921 } |
907 | 922 |
908 } } // namespace v8::internal | 923 } } // namespace v8::internal |
OLD | NEW |