| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 interface Scanner { | 5 interface Scanner { |
| 6 Token tokenize(); | 6 Token tokenize(); |
| 7 } | 7 } |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * Common base class for a Dart scanner. | 10 * Common base class for a Dart scanner. |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 // TODO(ahe): Would a range check be faster? | 249 // TODO(ahe): Would a range check be faster? |
| 250 if (next === $1 || next === $2 || next === $3 || next === $4 || next === $5 | 250 if (next === $1 || next === $2 || next === $3 || next === $4 || next === $5 |
| 251 || next === $6 || next === $7 || next === $8 || next === $9) { | 251 || next === $6 || next === $7 || next === $8 || next === $9) { |
| 252 return tokenizeNumber(next); | 252 return tokenizeNumber(next); |
| 253 } | 253 } |
| 254 | 254 |
| 255 if (next === $EOF) { | 255 if (next === $EOF) { |
| 256 return $EOF; | 256 return $EOF; |
| 257 } | 257 } |
| 258 if (next < 0x1f) { | 258 if (next < 0x1f) { |
| 259 throw new MalformedInputException("illegal character $next", charOffset); | 259 return error(new SourceString("unexpected character $next")); |
| 260 } | 260 } |
| 261 | 261 |
| 262 // The following are non-ASCII characters. | 262 // The following are non-ASCII characters. |
| 263 | 263 |
| 264 if (next === $NBSP) { | 264 if (next === $NBSP) { |
| 265 appendWhiteSpace(next); | 265 appendWhiteSpace(next); |
| 266 return advance(); | 266 return advance(); |
| 267 } | 267 } |
| 268 | 268 |
| 269 return tokenizeIdentifier(next, byteOffset, true); | 269 return tokenizeIdentifier(next, byteOffset, true); |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 int start = byteOffset - 1; | 485 int start = byteOffset - 1; |
| 486 bool hasDigits = false; | 486 bool hasDigits = false; |
| 487 while (true) { | 487 while (true) { |
| 488 next = advance(); | 488 next = advance(); |
| 489 if (($0 <= next && next <= $9) | 489 if (($0 <= next && next <= $9) |
| 490 || ($A <= next && next <= $F) | 490 || ($A <= next && next <= $F) |
| 491 || ($a <= next && next <= $f)) { | 491 || ($a <= next && next <= $f)) { |
| 492 hasDigits = true; | 492 hasDigits = true; |
| 493 } else { | 493 } else { |
| 494 if (!hasDigits) { | 494 if (!hasDigits) { |
| 495 throw new MalformedInputException("hex digit expected", charOffset); | 495 return error(const SourceString("hex digit expected")); |
| 496 } | 496 } |
| 497 appendByteStringToken(HEXADECIMAL_INFO, asciiString(start, 0)); | 497 appendByteStringToken(HEXADECIMAL_INFO, asciiString(start, 0)); |
| 498 return next; | 498 return next; |
| 499 } | 499 } |
| 500 } | 500 } |
| 501 } | 501 } |
| 502 | 502 |
| 503 int tokenizeDotsOrNumber(int next) { | 503 int tokenizeDotsOrNumber(int next) { |
| 504 int start = byteOffset; | 504 int start = byteOffset; |
| 505 next = advance(); | 505 next = advance(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 int tokenizeExponent(int next) { | 549 int tokenizeExponent(int next) { |
| 550 if (next === $PLUS || next === $MINUS) { | 550 if (next === $PLUS || next === $MINUS) { |
| 551 next = advance(); | 551 next = advance(); |
| 552 } | 552 } |
| 553 bool hasDigits = false; | 553 bool hasDigits = false; |
| 554 while (true) { | 554 while (true) { |
| 555 if ($0 <= next && next <= $9) { | 555 if ($0 <= next && next <= $9) { |
| 556 hasDigits = true; | 556 hasDigits = true; |
| 557 } else { | 557 } else { |
| 558 if (!hasDigits) { | 558 if (!hasDigits) { |
| 559 throw new MalformedInputException("digit expected", charOffset); | 559 return error(const SourceString("digit expected")); |
| 560 } | 560 } |
| 561 return next; | 561 return next; |
| 562 } | 562 } |
| 563 next = advance(); | 563 next = advance(); |
| 564 } | 564 } |
| 565 } | 565 } |
| 566 | 566 |
| 567 int tokenizeSlashOrComment(int next) { | 567 int tokenizeSlashOrComment(int next) { |
| 568 next = advance(); | 568 next = advance(); |
| 569 if ($STAR === next) { | 569 if ($STAR === next) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 } | 671 } |
| 672 | 672 |
| 673 while (true) { | 673 while (true) { |
| 674 if (($a <= next && next <= $z) || | 674 if (($a <= next && next <= $z) || |
| 675 ($A <= next && next <= $Z) || | 675 ($A <= next && next <= $Z) || |
| 676 ($0 <= next && next <= $9) || | 676 ($0 <= next && next <= $9) || |
| 677 next === $_ || | 677 next === $_ || |
| 678 (next === $$ && allowDollar)) { | 678 (next === $$ && allowDollar)) { |
| 679 isDynamicBuiltIn = false; | 679 isDynamicBuiltIn = false; |
| 680 next = advance(); | 680 next = advance(); |
| 681 } else if (next < 128) { | 681 } else if ((next < 128) || (next === $NBSP)) { |
| 682 // Identifier ends here. | 682 // Identifier ends here. |
| 683 if (start == byteOffset) { | 683 if (start == byteOffset) { |
| 684 throw new MalformedInputException("expected identifier not found", | 684 return error(const SourceString("expected identifier")); |
| 685 charOffset); | 685 } else if (isDynamicBuiltIn) { |
| 686 } | |
| 687 if (isDynamicBuiltIn) { | |
| 688 appendKeywordToken(Keyword.DYNAMIC); | 686 appendKeywordToken(Keyword.DYNAMIC); |
| 689 } else if (isAscii) { | 687 } else if (isAscii) { |
| 690 appendByteStringToken(IDENTIFIER_INFO, asciiString(start, 0)); | 688 appendByteStringToken(IDENTIFIER_INFO, asciiString(start, 0)); |
| 691 } else { | 689 } else { |
| 692 appendByteStringToken(IDENTIFIER_INFO, utf8String(start, -1)); | 690 appendByteStringToken(BAD_INPUT_INFO, utf8String(start, -1)); |
| 693 } | 691 } |
| 694 return next; | 692 return next; |
| 695 } else { | 693 } else { |
| 696 isDynamicBuiltIn = false; | 694 isDynamicBuiltIn = false; |
| 697 int nonAsciiStart = byteOffset; | 695 int nonAsciiStart = byteOffset; |
| 698 do { | 696 do { |
| 699 next = nextByte(); | 697 next = nextByte(); |
| 698 if (next === $NBSP) break; |
| 700 } while (next > 127); | 699 } while (next > 127); |
| 701 String string = utf8String(nonAsciiStart, -1).slowToString(); | 700 String string = utf8String(nonAsciiStart, -1).slowToString(); |
| 702 isAscii = false; | 701 isAscii = false; |
| 703 int byteLength = nonAsciiStart - byteOffset; | 702 int byteLength = nonAsciiStart - byteOffset; |
| 704 addToCharOffset(string.length - byteLength); | 703 addToCharOffset(string.length - byteLength); |
| 705 } | 704 } |
| 706 } | 705 } |
| 707 } | 706 } |
| 708 | 707 |
| 709 int tokenizeAtOrRawString(int next) { | 708 int tokenizeAtOrRawString(int next) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 int tokenizeSingleLineString(int next, int quoteChar, int start) { | 746 int tokenizeSingleLineString(int next, int quoteChar, int start) { |
| 748 while (next !== quoteChar) { | 747 while (next !== quoteChar) { |
| 749 if (next === $BACKSLASH) { | 748 if (next === $BACKSLASH) { |
| 750 next = advance(); | 749 next = advance(); |
| 751 } else if (next === $$) { | 750 } else if (next === $$) { |
| 752 next = tokenizeStringInterpolation(start); | 751 next = tokenizeStringInterpolation(start); |
| 753 start = byteOffset; | 752 start = byteOffset; |
| 754 continue; | 753 continue; |
| 755 } | 754 } |
| 756 if (next <= $CR && (next === $LF || next === $CR || next === $EOF)) { | 755 if (next <= $CR && (next === $LF || next === $CR || next === $EOF)) { |
| 757 throw new MalformedInputException("unterminated string literal", | 756 return error(const SourceString("unterminated string literal")); |
| 758 charOffset); | |
| 759 } | 757 } |
| 760 next = advance(); | 758 next = advance(); |
| 761 } | 759 } |
| 762 appendByteStringToken(STRING_INFO, utf8String(start, 0)); | 760 appendByteStringToken(STRING_INFO, utf8String(start, 0)); |
| 763 return advance(); | 761 return advance(); |
| 764 } | 762 } |
| 765 | 763 |
| 766 int tokenizeStringInterpolation(int start) { | 764 int tokenizeStringInterpolation(int start) { |
| 767 appendByteStringToken(STRING_INFO, utf8String(start, -1)); | 765 appendByteStringToken(STRING_INFO, utf8String(start, -1)); |
| 768 beginToken(); // $ starts here. | 766 beginToken(); // $ starts here. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 795 return next; | 793 return next; |
| 796 } | 794 } |
| 797 | 795 |
| 798 int tokenizeSingleLineRawString(int next, int quoteChar, int start) { | 796 int tokenizeSingleLineRawString(int next, int quoteChar, int start) { |
| 799 next = advance(); | 797 next = advance(); |
| 800 while (next != $EOF) { | 798 while (next != $EOF) { |
| 801 if (next === quoteChar) { | 799 if (next === quoteChar) { |
| 802 appendByteStringToken(STRING_INFO, utf8String(start, 0)); | 800 appendByteStringToken(STRING_INFO, utf8String(start, 0)); |
| 803 return advance(); | 801 return advance(); |
| 804 } else if (next === $LF || next === $CR) { | 802 } else if (next === $LF || next === $CR) { |
| 805 throw new MalformedInputException("unterminated string literal", | 803 return error(const SourceString("unterminated string literal")); |
| 806 charOffset); | |
| 807 } | 804 } |
| 808 next = advance(); | 805 next = advance(); |
| 809 } | 806 } |
| 810 throw new MalformedInputException("unterminated string literal", | 807 return error(const SourceString("unterminated string literal")); |
| 811 charOffset); | |
| 812 } | 808 } |
| 813 | 809 |
| 814 int tokenizeMultiLineRawString(int quoteChar, int start) { | 810 int tokenizeMultiLineRawString(int quoteChar, int start) { |
| 815 int next = advance(); | 811 int next = advance(); |
| 816 outer: while (next !== $EOF) { | 812 outer: while (next !== $EOF) { |
| 817 while (next !== quoteChar) { | 813 while (next !== quoteChar) { |
| 818 next = advance(); | 814 next = advance(); |
| 819 if (next === $EOF) break outer; | 815 if (next === $EOF) break outer; |
| 820 } | 816 } |
| 821 next = advance(); | 817 next = advance(); |
| 822 if (next === quoteChar) { | 818 if (next === quoteChar) { |
| 823 next = advance(); | 819 next = advance(); |
| 824 if (next === quoteChar) { | 820 if (next === quoteChar) { |
| 825 appendByteStringToken(STRING_INFO, utf8String(start, 0)); | 821 appendByteStringToken(STRING_INFO, utf8String(start, 0)); |
| 826 return advance(); | 822 return advance(); |
| 827 } | 823 } |
| 828 } | 824 } |
| 829 } | 825 } |
| 830 throw new MalformedInputException("unterminated string literal", | 826 return error(const SourceString("unterminated string literal")); |
| 831 charOffset); | |
| 832 } | 827 } |
| 833 | 828 |
| 834 int tokenizeMultiLineString(int quoteChar, int start, bool raw) { | 829 int tokenizeMultiLineString(int quoteChar, int start, bool raw) { |
| 835 if (raw) return tokenizeMultiLineRawString(quoteChar, start); | 830 if (raw) return tokenizeMultiLineRawString(quoteChar, start); |
| 836 int next = advance(); | 831 int next = advance(); |
| 837 while (next !== $EOF) { | 832 while (next !== $EOF) { |
| 838 if (next === $$) { | 833 if (next === $$) { |
| 839 next = tokenizeStringInterpolation(start); | 834 next = tokenizeStringInterpolation(start); |
| 840 start = byteOffset; | 835 start = byteOffset; |
| 841 continue; | 836 continue; |
| 842 } | 837 } |
| 843 if (next === quoteChar) { | 838 if (next === quoteChar) { |
| 844 next = advance(); | 839 next = advance(); |
| 845 if (next === quoteChar) { | 840 if (next === quoteChar) { |
| 846 next = advance(); | 841 next = advance(); |
| 847 if (next === quoteChar) { | 842 if (next === quoteChar) { |
| 848 appendByteStringToken(STRING_INFO, utf8String(start, 0)); | 843 appendByteStringToken(STRING_INFO, utf8String(start, 0)); |
| 849 return advance(); | 844 return advance(); |
| 850 } | 845 } |
| 851 } | 846 } |
| 852 continue; | 847 continue; |
| 853 } | 848 } |
| 854 if (next === $BACKSLASH) { | 849 if (next === $BACKSLASH) { |
| 855 next = advance(); | 850 next = advance(); |
| 856 if (next === $EOF) break; | 851 if (next === $EOF) break; |
| 857 } | 852 } |
| 858 next = advance(); | 853 next = advance(); |
| 859 } | 854 } |
| 860 throw new MalformedInputException("unterminated string literal", | 855 return error(const SourceString("unterminated string literal")); |
| 861 charOffset); | 856 } |
| 857 |
| 858 int error(SourceString message) { |
| 859 appendByteStringToken(BAD_INPUT_INFO, message); |
| 860 return advance(); // Ensure progress. |
| 862 } | 861 } |
| 863 } | 862 } |
| 864 | |
| 865 class MalformedInputException { | |
| 866 final String message; | |
| 867 final position; | |
| 868 MalformedInputException(this.message, this.position); | |
| 869 toString() => message; | |
| 870 } | |
| OLD | NEW |