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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/scanner/scanner.dart

Issue 40583002: Incorporates feedback by Nicolas for UTF-8 bytes based scanner CL (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months 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 (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 part of scanner; 5 part of scanner;
6 6
7 abstract class Scanner { 7 abstract class Scanner {
8 Token tokenize(); 8 Token tokenize();
9 9
10 factory Scanner(SourceFile file, {bool includeComments: false}) { 10 factory Scanner(SourceFile file, {bool includeComments: false}) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 */ 42 */
43 Token tail; 43 Token tail;
44 44
45 /** 45 /**
46 * The source file that is being scanned. This field can be [:null:]. 46 * The source file that is being scanned. This field can be [:null:].
47 * If the source file is available, the scanner assigns its [:lineStarts:] and 47 * If the source file is available, the scanner assigns its [:lineStarts:] and
48 * [:length:] fields at the end of [tokenize]. 48 * [:length:] fields at the end of [tokenize].
49 */ 49 */
50 final SourceFile file; 50 final SourceFile file;
51 51
52 final List<int> lineStarts = [0]; 52 final List<int> lineStarts = <int>[0];
53 53
54 AbstractScanner(this.file, this.includeComments) { 54 AbstractScanner(this.file, this.includeComments) {
55 this.tail = this.tokens; 55 this.tail = this.tokens;
56 } 56 }
57 57
58
59 /** 58 /**
60 * Advances and returns the next character. 59 * Advances and returns the next character.
61 * 60 *
62 * If the next character is non-ASCII, then the returned value depends on the 61 * If the next character is non-ASCII, then the returned value depends on the
63 * scanner implementation. The [Utf8BytesScanner] returns a UTF-8 byte, while 62 * scanner implementation. The [Utf8BytesScanner] returns a UTF-8 byte, while
64 * the [StringScanner] returns a UTF-16 code unit. 63 * the [StringScanner] returns a UTF-16 code unit.
65 * 64 *
66 * The scanner ensures that [advance] is not invoked after it returned [$EOF]. 65 * The scanner ensures that [advance] is not invoked after it returned [$EOF].
67 * This allows implementations to omit bound checks if the data structure ends 66 * This allows implementations to omit bound checks if the data structure ends
68 * with '0'. 67 * with '0'.
69 */ 68 */
70 int advance(); 69 int advance();
71 70
72 /** 71 /**
73 * Returns the current unicode character. 72 * Returns the current unicode character.
74 * 73 *
75 * If the current character is ASCII, then it is returned unchanged. 74 * If the current character is ASCII, then it is returned unchanged.
76 * 75 *
77 * The [Utf8BytesScanner] decodes the next unicode code point starting at the 76 * The [Utf8BytesScanner] decodes the next unicode code point starting at the
78 * current position. Note that every unicode character is returned as a single 77 * current position. Note that every unicode character is returned as a single
79 * code point, i.e., for '\u{1d11e}' it returns 119070, and the following 78 * code point, that is, for '\u{1d11e}' it returns 119070, and the following
80 * [advance] returns the next character. 79 * [advance] returns the next character.
81 * 80 *
82 * The [StringScanner] returns the current character unchanged, which might 81 * The [StringScanner] returns the current character unchanged, which might
83 * be a surrogate character. In the case of '\u{1d11e}', it returns the first 82 * be a surrogate character. In the case of '\u{1d11e}', it returns the first
84 * code unit 55348, and the following [advance] returns the second code unit 83 * code unit 55348, and the following [advance] returns the second code unit
85 * 56606. 84 * 56606.
86 * 85 *
87 * Invoking [currentAsUnicode] multiple times is safe, i.e., 86 * Invoking [currentAsUnicode] multiple times is safe, i.e.,
88 * [:currentAsUnicode(next) == currentAsUnicode(currentAsUnicode(next)):]. 87 * [:currentAsUnicode(next) == currentAsUnicode(currentAsUnicode(next)):].
89 */ 88 */
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 } 847 }
849 } 848 }
850 if (raw) { 849 if (raw) {
851 return tokenizeSingleLineRawString(next, quoteChar, start); 850 return tokenizeSingleLineRawString(next, quoteChar, start);
852 } else { 851 } else {
853 return tokenizeSingleLineString(next, quoteChar, start); 852 return tokenizeSingleLineString(next, quoteChar, start);
854 } 853 }
855 } 854 }
856 855
857 /** 856 /**
858 * [next] is the first character after the qoute. 857 * [next] is the first character after the quote.
859 * [start] is the scanOffset of the quote. 858 * [start] is the scanOffset of the quote.
860 * 859 *
861 * The token contains a substring of the source file, including the 860 * The token contains a substring of the source file, including the
862 * string quotes, backslashes for escaping. For interpolated strings, 861 * string quotes, backslashes for escaping. For interpolated strings,
863 * the parts before and after are separate tokens. 862 * the parts before and after are separate tokens.
864 * 863 *
865 * "a $b c" 864 * "a $b c"
866 * 865 *
867 * gives StringToken("a $), StringToken(b) and StringToken( c"). 866 * gives StringToken("a $), StringToken(b) and StringToken( c").
868 */ 867 */
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 int tokenizeInterpolatedIdentifier(int next) { 921 int tokenizeInterpolatedIdentifier(int next) {
923 appendPrecedenceToken(STRING_INTERPOLATION_IDENTIFIER_INFO); 922 appendPrecedenceToken(STRING_INTERPOLATION_IDENTIFIER_INFO);
924 beginToken(); // The identifier starts here. 923 beginToken(); // The identifier starts here.
925 next = tokenizeKeywordOrIdentifier(next, false); 924 next = tokenizeKeywordOrIdentifier(next, false);
926 beginToken(); // The string interpolation suffix starts here. 925 beginToken(); // The string interpolation suffix starts here.
927 return next; 926 return next;
928 } 927 }
929 928
930 int tokenizeSingleLineRawString(int next, int quoteChar, int start) { 929 int tokenizeSingleLineRawString(int next, int quoteChar, int start) {
931 bool asciiOnly = true; 930 bool asciiOnly = true;
932 next = advance(); // Advance past the quote 931 next = advance(); // Advance past the quote.
933 while (next != $EOF) { 932 while (next != $EOF) {
934 if (identical(next, quoteChar)) { 933 if (identical(next, quoteChar)) {
935 if (!asciiOnly) handleUnicode(start); 934 if (!asciiOnly) handleUnicode(start);
936 next = advance(); 935 next = advance();
937 appendSubstringToken(STRING_INFO, start, asciiOnly); 936 appendSubstringToken(STRING_INFO, start, asciiOnly);
938 return next; 937 return next;
939 } else if (identical(next, $LF) || identical(next, $CR)) { 938 } else if (identical(next, $LF) || identical(next, $CR)) {
940 if (!asciiOnly) handleUnicode(start); 939 if (!asciiOnly) handleUnicode(start);
941 return error("unterminated string literal"); 940 return error("unterminated string literal");
942 } else if (next > 127) { 941 } else if (next > 127) {
943 asciiOnly = false; 942 asciiOnly = false;
944 } 943 }
945 next = advance(); 944 next = advance();
946 } 945 }
947 if (!asciiOnly) handleUnicode(start); 946 if (!asciiOnly) handleUnicode(start);
948 return error("unterminated string literal"); 947 return error("unterminated string literal");
949 } 948 }
950 949
951 int tokenizeMultiLineRawString(int quoteChar, int start) { 950 int tokenizeMultiLineRawString(int quoteChar, int start) {
952 bool asciiOnlyString = true; 951 bool asciiOnlyString = true;
953 bool asciiOnlyLine = true; 952 bool asciiOnlyLine = true;
954 int unicodeStart = start; 953 int unicodeStart = start;
955 int next = advance(); // Advance past the (last) quote (of three) 954 int next = advance(); // Advance past the (last) quote (of three).
956 outer: while (!identical(next, $EOF)) { 955 outer: while (!identical(next, $EOF)) {
957 while (!identical(next, quoteChar)) { 956 while (!identical(next, quoteChar)) {
958 if (identical(next, $LF)) { 957 if (identical(next, $LF)) {
959 if (!asciiOnlyLine) { 958 if (!asciiOnlyLine) {
960 // Synchronize the string offset in the utf8 scanner. 959 // Synchronize the string offset in the utf8 scanner.
961 handleUnicode(unicodeStart); 960 handleUnicode(unicodeStart);
962 asciiOnlyLine = true; 961 asciiOnlyLine = true;
963 unicodeStart = scanOffset; 962 unicodeStart = scanOffset;
964 } 963 }
965 lineFeedInMultiline(); 964 lineFeedInMultiline();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 1037
1039 int error(String message) { 1038 int error(String message) {
1040 appendStringToken(BAD_INPUT_INFO, message); 1039 appendStringToken(BAD_INPUT_INFO, message);
1041 return advance(); // Ensure progress. 1040 return advance(); // Ensure progress.
1042 } 1041 }
1043 1042
1044 void unmatchedBeginGroup(BeginGroupToken begin) { 1043 void unmatchedBeginGroup(BeginGroupToken begin) {
1045 String error = 'unmatched "${begin.stringValue}"'; 1044 String error = 'unmatched "${begin.stringValue}"';
1046 Token close = 1045 Token close =
1047 new StringToken.fromString( 1046 new StringToken.fromString(
1048 BAD_INPUT_INFO, error, begin.charOffset, true); 1047 BAD_INPUT_INFO, error, begin.charOffset, canonicalize: true);
1049 1048
1050 // We want to ensure that unmatched BeginGroupTokens are reported 1049 // We want to ensure that unmatched BeginGroupTokens are reported
1051 // as errors. However, the rest of the parser assume the groups 1050 // as errors. However, the rest of the parser assumes the groups
1052 // are well-balanced and will never look at the endGroup 1051 // are well-balanced and will never look at the endGroup
1053 // token. This is a nice property that allows us to skip quickly 1052 // token. This is a nice property that allows us to skip quickly
1054 // over correct code. By inserting an additional error token in 1053 // over correct code. By inserting an additional error token in
1055 // the stream, we can keep ignoring endGroup tokens. 1054 // the stream, we can keep ignoring endGroup tokens.
1056 // 1055 //
1057 // [begin] --next--> [tail] 1056 // [begin] --next--> [tail]
1058 // [begin] --endG--> [close] --next--> [next] --next--> [tail] 1057 // [begin] --endG--> [close] --next--> [next] --next--> [tail]
1059 // 1058 //
1060 // This allows the parser to skip from [begin] via endGroup to [close] and 1059 // This allows the parser to skip from [begin] via endGroup to [close] and
1061 // ignore the [close] token (assuming it's correct), then the error will be 1060 // ignore the [close] token (assuming it's correct), then the error will be
1062 // reported when parsing the [next] token. 1061 // reported when parsing the [next] token.
1063 1062
1064 Token next = new StringToken.fromString( 1063 Token next = new StringToken.fromString(
1065 BAD_INPUT_INFO, error, begin.charOffset, true); 1064 BAD_INPUT_INFO, error, begin.charOffset, canonicalize: true);
1066 begin.endGroup = close; 1065 begin.endGroup = close;
1067 close.next = next; 1066 close.next = next;
1068 next.next = begin.next; 1067 next.next = begin.next;
1069 } 1068 }
1070 } 1069 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698