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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/scanner/token.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, 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 (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 const int EOF_TOKEN = 0; 7 const int EOF_TOKEN = 0;
8 8
9 const int KEYWORD_TOKEN = $k; 9 const int KEYWORD_TOKEN = $k;
10 const int IDENTIFIER_TOKEN = $a; 10 const int IDENTIFIER_TOKEN = $a;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 * The precedence info for this token. [info] determines the kind and the 96 * The precedence info for this token. [info] determines the kind and the
97 * precedence level of this token. 97 * precedence level of this token.
98 * 98 *
99 * Defined as getter to save a field in the [KeywordToken] subclass. 99 * Defined as getter to save a field in the [KeywordToken] subclass.
100 */ 100 */
101 PrecedenceInfo get info; 101 PrecedenceInfo get info;
102 102
103 /** 103 /**
104 * The string represented by this token, a substring of the source code. 104 * The string represented by this token, a substring of the source code.
105 * 105 *
106 * For [StringToken]s the value includes the quotes, explicit escapes, etc. 106 * For [StringToken]s the [value] includes the quotes, explicit escapes, etc.
107 *
108 */ 107 */
109 String get value; 108 String get value;
110 109
111 /** 110 /**
112 * For symbol and keyword tokens, returns the string value reprenseted by this 111 * For symbol and keyword tokens, returns the string value represented by this
113 * token. For [StringToken]s this method returns [:null:]. 112 * token. For [StringToken]s this method returns [:null:].
114 * 113 *
115 * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time 114 * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time
116 * constant originating in the [PrecedenceInfo] or in the [Keyword] instance. 115 * constant originating in the [PrecedenceInfo] or in the [Keyword] instance.
117 * This allows testing for keywords and symbols using [:identical:], e.g., 116 * This allows testing for keywords and symbols using [:identical:], e.g.,
118 * [:identical('class', token.value):]. 117 * [:identical('class', token.value):].
119 * 118 *
120 * Note that returning [:null:] for string tokens is important to identify 119 * Note that returning [:null:] for string tokens is important to identify
121 * symbols and keywords, we cannot use [value] instead. The string literal 120 * symbols and keywords, we cannot use [value] instead. The string literal
122 * "$a($b" 121 * "$a($b"
(...skipping 10 matching lines...) Expand all
133 */ 132 */
134 int get kind => info.kind; 133 int get kind => info.kind;
135 134
136 /** 135 /**
137 * The precedence level for this token. 136 * The precedence level for this token.
138 */ 137 */
139 int get precedence => info.precedence; 138 int get precedence => info.precedence;
140 139
141 /** 140 /**
142 * True if this token is an identifier. Some keywords allowed as identifiers, 141 * True if this token is an identifier. Some keywords allowed as identifiers,
143 * see implementaiton in [KeywordToken]. 142 * see implementation in [KeywordToken].
144 */ 143 */
145 bool isIdentifier(); 144 bool isIdentifier();
146 145
147 /** 146 /**
148 * Returns a textual representation of this token to be used for debugging 147 * Returns a textual representation of this token to be used for debugging
149 * purposes. The resulting string might contain information about the 148 * purposes. The resulting string might contain information about the
150 * structure of the token, for example 'StringToken(foo)' for the identifier 149 * structure of the token, for example 'StringToken(foo)' for the identifier
151 * token 'foo'. 150 * token 'foo'.
152 * 151 *
153 * Use [value] for the text actually parsed by the token. 152 * Use [value] for the text actually parsed by the token.
(...skipping 10 matching lines...) Expand all
164 return 1; 163 return 1;
165 } else { 164 } else {
166 return value.length; 165 return value.length;
167 } 166 }
168 } 167 }
169 168
170 int get hashCode => computeHashCode(charOffset, info, value); 169 int get hashCode => computeHashCode(charOffset, info, value);
171 } 170 }
172 171
173 /** 172 /**
174 * A symbol token represents the symbol in its precendence info. 173 * A [SymbolToken] represents the symbol in its precendence info.
175 * Also used for end of file with EOF_INFO. 174 * Also used for end of file with EOF_INFO.
176 */ 175 */
177 class SymbolToken extends Token { 176 class SymbolToken extends Token {
178 177
179 final PrecedenceInfo info; 178 final PrecedenceInfo info;
180 179
181 SymbolToken(this.info, int charOffset) : super(charOffset); 180 SymbolToken(this.info, int charOffset) : super(charOffset);
182 181
183 String get value => info.value; 182 String get value => info.value;
184 183
185 String get stringValue => info.value; 184 String get stringValue => info.value;
186 185
187 bool isIdentifier() => false; 186 bool isIdentifier() => false;
188 187
189 String toString() => "SymbolToken($value)"; 188 String toString() => "SymbolToken($value)";
190 } 189 }
191 190
192 /** 191 /**
193 * A [BeginGroupToken] reprsents a symbol that may be the beginning of 192 * A [BeginGroupToken] represents a symbol that may be the beginning of
194 * a pair of brackets, i.e., ( { [ < or ${ 193 * a pair of brackets, i.e., ( { [ < or ${
195 * The [endGroup] token points to the matching closing bracked in case 194 * The [endGroup] token points to the matching closing bracked in case
196 * it can be identified during scanning. 195 * it can be identified during scanning.
197 */ 196 */
198 class BeginGroupToken extends SymbolToken { 197 class BeginGroupToken extends SymbolToken {
199 Token endGroup; 198 Token endGroup;
200 199
201 BeginGroupToken(PrecedenceInfo info, int charOffset) 200 BeginGroupToken(PrecedenceInfo info, int charOffset)
202 : super(info, charOffset); 201 : super(info, charOffset);
203 } 202 }
204 203
205 /** 204 /**
206 * A keyword token. 205 * A keyword token.
207 */ 206 */
208 class KeywordToken extends Token { 207 class KeywordToken extends Token {
209 final Keyword keyword; 208 final Keyword keyword;
210 209
211 KeywordToken(this.keyword, int charOffset) : super(charOffset); 210 KeywordToken(this.keyword, int charOffset) : super(charOffset);
212 211
213 PrecedenceInfo get info => keyword.info; 212 PrecedenceInfo get info => keyword.info;
214 213
215 String get value => keyword.syntax; 214 String get value => keyword.syntax;
216 215
217 String get stringValue => keyword.syntax; 216 String get stringValue => keyword.syntax;
218 217
219 bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn; 218 bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn;
220 219
221 String toString() => "KeywordToken($value)"; 220 String toString() => "KeywordToken($value)";
222 } 221 }
223 222
224 /** 223 /**
225 * A String-valued token. Represents identifiers, string literals, 224 * A String-valued token. Represents identifiers, string literals,
226 * number literals, comments and error tokens, using the corresponding 225 * number literals, comments, and error tokens, using the corresponding
227 * precedence info. 226 * precedence info.
228 */ 227 */
229 class StringToken extends Token { 228 class StringToken extends Token {
230 /** 229 /**
231 * The length threshold above which substring tokens are computed lazily. 230 * The length threshold above which substring tokens are computed lazily.
232 * 231 *
233 * For string tokens that are substrings of the program source, the actual 232 * For string tokens that are substrings of the program source, the actual
234 * substring extraction is performed lazily. This is beneficial because 233 * substring extraction is performed lazily. This is beneficial because
235 * not all scanned code is actually used. For unused parts, the substrings 234 * not all scanned code is actually used. For unused parts, the substrings
236 * are never computed and allocated. 235 * are never computed and allocated.
237 */ 236 */
238 static const int LAZY_THRESHOLD = 4; 237 static const int LAZY_THRESHOLD = 4;
239 238
240 var valueOrLazySubstring; 239 var /* String | LazySubtring */ valueOrLazySubstring;
241 240
242 final PrecedenceInfo info; 241 final PrecedenceInfo info;
243 242
244 /** 243 /**
245 * Creates a non-lazy string token. If [canonicalize] is true, the string 244 * Creates a non-lazy string token. If [canonicalize] is true, the string
246 * is canonicalized before the token is created. 245 * is canonicalized before the token is created.
247 */ 246 */
248 StringToken.fromString(this.info, String value, int charOffset, 247 StringToken.fromString(this.info, String value, int charOffset,
249 [bool canonicalize = false]) 248 {bool canonicalize : false})
250 : valueOrLazySubstring = canonicalizedString(value, canonicalize), 249 : valueOrLazySubstring = canonicalizedString(value, canonicalize),
251 super(charOffset); 250 super(charOffset);
252 251
253 /** 252 /**
254 * Creates a lazy string token. If [canonicalize] is true, the string 253 * Creates a lazy string token. If [canonicalize] is true, the string
255 * is canonicalized before the token is created. 254 * is canonicalized before the token is created.
256 */ 255 */
257 StringToken.fromSubstring(this.info, String data, int start, int end, 256 StringToken.fromSubstring(this.info, String data, int start, int end,
258 int charOffset, [bool canonicalize = false]) 257 int charOffset, {bool canonicalize : false})
259 : super(charOffset) { 258 : super(charOffset) {
260 int length = end - start; 259 int length = end - start;
261 if (length <= LAZY_THRESHOLD) { 260 if (length <= LAZY_THRESHOLD) {
262 valueOrLazySubstring = canonicalizedString(data.substring(start, end), 261 valueOrLazySubstring = canonicalizedString(data.substring(start, end),
263 canonicalize); 262 canonicalize);
264 } else { 263 } else {
265 valueOrLazySubstring = 264 valueOrLazySubstring =
266 new LazySubstring(data, start, length, canonicalize); 265 new LazySubstring(data, start, length, canonicalize);
267 } 266 }
268 } 267 }
269 268
270 /** 269 /**
271 * Creates a lazy string token. If [asciiOnly] is false, the byte array 270 * Creates a lazy string token. If [asciiOnly] is false, the byte array
272 * is passed through a UTF-8 decoder. 271 * is passed through a UTF-8 decoder.
273 */ 272 */
(...skipping 27 matching lines...) Expand all
301 } 300 }
302 } 301 }
303 302
304 String get stringValue => null; 303 String get stringValue => null;
305 304
306 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN); 305 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN);
307 306
308 String toString() => "StringToken($value)"; 307 String toString() => "StringToken($value)";
309 308
310 static final HashSet<String> canonicalizedSubstrings = 309 static final HashSet<String> canonicalizedSubstrings =
311 new HashSet(); 310 new HashSet<String>();
312 311
313 static String canonicalizedString(String s, bool canonicalize) { 312 static String canonicalizedString(String s, bool canonicalize) {
314 if (!canonicalize) return s; 313 if (!canonicalize) return s;
315 var result = canonicalizedSubstrings.lookup(s); 314 var result = canonicalizedSubstrings.lookup(s);
316 if (result != null) return result; 315 if (result != null) return result;
317 canonicalizedSubstrings.add(s); 316 canonicalizedSubstrings.add(s);
318 return s; 317 return s;
319 } 318 }
320 319
321 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) { 320 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) {
322 var s; 321 var s;
323 if (asciiOnly) { 322 if (asciiOnly) {
324 // getRange returns an iterator, it does not copy the data. 323 // getRange returns an iterator, it does not copy the data.
325 s = new String.fromCharCodes(data.getRange(start, end)); 324 s = new String.fromCharCodes(data.getRange(start, end));
326 } else { 325 } else {
327 // TODO(lry): this is measurably slow. Also sublist is copied eagerly. 326 // TODO(lry): this is measurably slow. Also sublist is copied eagerly.
328 var bytes = data.sublist(start, end); 327 var bytes = data.sublist(start, end);
329 s = UTF8.decode(bytes); 328 s = UTF8.decode(bytes);
330 } 329 }
331 return canonicalizedString(s, true); 330 return canonicalizedString(s, true);
332 } 331 }
333 } 332 }
334 333
335 /** 334 /**
336 * This class represents the necessary information to compute a substring 335 * This class represents the necessary information to compute a substring
337 * lazily. The substring can either originate in a string or in a [:List<int>:] 336 * lazily. The substring can either originate from a string or from
338 * of UTF-8 bytes. 337 * a [:List<int>:] of UTF-8 bytes.
339 */ 338 */
340 abstract class LazySubstring { 339 abstract class LazySubstring {
341 /** The original data, either a string or a List<int> */ 340 /** The original data, either a string or a List<int> */
342 get data; 341 get data;
343 342
344 int get start; 343 int get start;
345 int get length; 344 int get length;
346 345
347 /** 346 /**
348 * If this substring is based on a String, the boolean indicates wheter the 347 * If this substring is based on a String, the [boolValue] indicates wheter
349 * resulting substring should be canonicalized. 348 * the resulting substring should be canonicalized.
350 * 349 *
351 * For substrings based on a byte array, the boolean value is true if the 350 * For substrings based on a byte array, the [boolValue] is true if the
352 * array only holds ASCII characters. The resulting substring will be 351 * array only holds ASCII characters. The resulting substring will be
353 * canonicalized after decoding. 352 * canonicalized after decoding.
354 */ 353 */
355 bool get boolValue; 354 bool get boolValue;
356 355
357 LazySubstring.internal(); 356 LazySubstring.internal();
358 357
359 factory LazySubstring(data, int start, int length, bool b) { 358 factory LazySubstring(data, int start, int length, bool b) {
360 // See comment on [CompactLazySubstring]. 359 // See comment on [CompactLazySubstring].
361 if (start < 0x100000 && length < 0x200) { 360 if (start < 0x100000 && length < 0x200) {
362 int fields = (start << 9); 361 int fields = (start << 9);
363 fields = fields | length; 362 fields = fields | length;
364 fields = fields << 1; 363 fields = fields << 1;
365 if (b) fields |= 1; 364 if (b) fields |= 1;
366 return new CompactLazySubstring(data, fields); 365 return new CompactLazySubstring(data, fields);
367 } else { 366 } else {
368 return new FullLazySubstring(data, start, length, b); 367 return new FullLazySubstring(data, start, length, b);
369 } 368 }
370 } 369 }
371 } 370 }
372 371
373 /** 372 /**
374 * This class encodes [start], [length] and [boolValue] in a single 373 * This class encodes [start], [length] and [boolValue] in a single
375 * 30 bit integer. It uses 20 bits for [start], which covers source files 374 * 30 bit integer. It uses 20 bits for [start], which covers source files
376 * of 1M. [length] has 9 bits, which covers 512 characters. 375 * of 1MB. [length] has 9 bits, which covers 512 characters.
377 * 376 *
378 * The file html_dart2js.dart is currently around 1M. 377 * The file html_dart2js.dart is currently around 1MB.
379 */ 378 */
380 class CompactLazySubstring extends LazySubstring { 379 class CompactLazySubstring extends LazySubstring {
381 final data; 380 final data;
382 final int fields; 381 final int fields;
383 382
384 CompactLazySubstring(this.data, this.fields) : super.internal(); 383 CompactLazySubstring(this.data, this.fields) : super.internal();
385 384
386 int get start => fields >> 10; 385 int get start => fields >> 10;
387 int get length => (fields >> 1) & 0x1ff; 386 int get length => (fields >> 1) & 0x1ff;
388 bool get boolValue => (fields & 1) == 1; 387 bool get boolValue => (fields & 1) == 1;
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 657
659 const PrecedenceInfo STRING_INTERPOLATION_IDENTIFIER_INFO = 658 const PrecedenceInfo STRING_INTERPOLATION_IDENTIFIER_INFO =
660 const PrecedenceInfo('\$', 0, 659 const PrecedenceInfo('\$', 0,
661 STRING_INTERPOLATION_IDENTIFIER_TOKEN); 660 STRING_INTERPOLATION_IDENTIFIER_TOKEN);
662 661
663 const PrecedenceInfo HEXADECIMAL_INFO = 662 const PrecedenceInfo HEXADECIMAL_INFO =
664 const PrecedenceInfo('hexadecimal', 0, HEXADECIMAL_TOKEN); 663 const PrecedenceInfo('hexadecimal', 0, HEXADECIMAL_TOKEN);
665 664
666 const PrecedenceInfo COMMENT_INFO = 665 const PrecedenceInfo COMMENT_INFO =
667 const PrecedenceInfo('comment', 0, COMMENT_TOKEN); 666 const PrecedenceInfo('comment', 0, COMMENT_TOKEN);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698