| OLD | NEW |
| 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 library fasta.scanner.token; | 5 library fasta.scanner.token; |
| 6 | 6 |
| 7 import 'dart:collection' show | 7 import 'dart:collection' show |
| 8 HashSet; | 8 HashSet; |
| 9 | 9 |
| 10 import 'dart:convert' show | 10 import 'dart:convert' show |
| 11 UTF8; | 11 UTF8; |
| 12 | 12 |
| 13 import 'keyword.dart' show | 13 import 'keyword.dart' show |
| 14 Keyword; | 14 Keyword; |
| 15 | 15 |
| 16 import 'precedence.dart' show | 16 import 'precedence.dart' show |
| 17 BAD_INPUT_INFO, | 17 BAD_INPUT_INFO, |
| 18 EOF_INFO, | 18 EOF_INFO, |
| 19 PrecedenceInfo; | 19 PrecedenceInfo; |
| 20 | 20 |
| 21 import 'token_constants.dart' show | 21 import 'token_constants.dart' show |
| 22 IDENTIFIER_TOKEN; | 22 IDENTIFIER_TOKEN; |
| 23 | 23 |
| 24 import 'canonicalizer.dart'; | |
| 25 | |
| 26 /** | 24 /** |
| 27 * A token that doubles as a linked list. | 25 * A token that doubles as a linked list. |
| 28 */ | 26 */ |
| 29 abstract class Token { | 27 abstract class Token { |
| 30 /** | 28 /** |
| 31 * The character offset of the start of this token within the source text. | 29 * The character offset of the start of this token within the source text. |
| 32 */ | 30 */ |
| 33 final int charOffset; | 31 final int charOffset; |
| 34 | 32 |
| 35 Token(this.charOffset); | 33 Token(this.charOffset); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 var /* String | LazySubtring */ valueOrLazySubstring; | 188 var /* String | LazySubtring */ valueOrLazySubstring; |
| 191 | 189 |
| 192 final PrecedenceInfo info; | 190 final PrecedenceInfo info; |
| 193 | 191 |
| 194 /** | 192 /** |
| 195 * Creates a non-lazy string token. If [canonicalize] is true, the string | 193 * Creates a non-lazy string token. If [canonicalize] is true, the string |
| 196 * is canonicalized before the token is created. | 194 * is canonicalized before the token is created. |
| 197 */ | 195 */ |
| 198 StringToken.fromString(this.info, String value, int charOffset, | 196 StringToken.fromString(this.info, String value, int charOffset, |
| 199 {bool canonicalize: false}) | 197 {bool canonicalize: false}) |
| 200 : valueOrLazySubstring = canonicalizedString(value, | 198 : valueOrLazySubstring = canonicalizedString(value, canonicalize), |
| 201 0, value.length, canonicalize), | |
| 202 super(charOffset); | 199 super(charOffset); |
| 203 | 200 |
| 204 /** | 201 /** |
| 205 * Creates a lazy string token. If [canonicalize] is true, the string | 202 * Creates a lazy string token. If [canonicalize] is true, the string |
| 206 * is canonicalized before the token is created. | 203 * is canonicalized before the token is created. |
| 207 */ | 204 */ |
| 208 StringToken.fromSubstring( | 205 StringToken.fromSubstring( |
| 209 this.info, String data, int start, int end, int charOffset, | 206 this.info, String data, int start, int end, int charOffset, |
| 210 {bool canonicalize: false}) | 207 {bool canonicalize: false}) |
| 211 : super(charOffset) { | 208 : super(charOffset) { |
| 212 int length = end - start; | 209 int length = end - start; |
| 213 if (length <= LAZY_THRESHOLD) { | 210 if (length <= LAZY_THRESHOLD) { |
| 214 valueOrLazySubstring = | 211 valueOrLazySubstring = |
| 215 canonicalizedString(data, start, end, canonicalize); | 212 canonicalizedString(data.substring(start, end), canonicalize); |
| 216 } else { | 213 } else { |
| 217 valueOrLazySubstring = | 214 valueOrLazySubstring = |
| 218 new LazySubstring(data, start, length, canonicalize); | 215 new LazySubstring(data, start, length, canonicalize); |
| 219 } | 216 } |
| 220 } | 217 } |
| 221 | 218 |
| 222 /** | 219 /** |
| 223 * Creates a lazy string token. If [asciiOnly] is false, the byte array | 220 * Creates a lazy string token. If [asciiOnly] is false, the byte array |
| 224 * is passed through a UTF-8 decoder. | 221 * is passed through a UTF-8 decoder. |
| 225 */ | 222 */ |
| (...skipping 11 matching lines...) Expand all Loading... |
| 237 String get value { | 234 String get value { |
| 238 if (valueOrLazySubstring is String) { | 235 if (valueOrLazySubstring is String) { |
| 239 return valueOrLazySubstring; | 236 return valueOrLazySubstring; |
| 240 } else { | 237 } else { |
| 241 assert(valueOrLazySubstring is LazySubstring); | 238 assert(valueOrLazySubstring is LazySubstring); |
| 242 var data = valueOrLazySubstring.data; | 239 var data = valueOrLazySubstring.data; |
| 243 int start = valueOrLazySubstring.start; | 240 int start = valueOrLazySubstring.start; |
| 244 int end = start + valueOrLazySubstring.length; | 241 int end = start + valueOrLazySubstring.length; |
| 245 if (data is String) { | 242 if (data is String) { |
| 246 valueOrLazySubstring = canonicalizedString( | 243 valueOrLazySubstring = canonicalizedString( |
| 247 data, start, end, valueOrLazySubstring.boolValue); | 244 data.substring(start, end), valueOrLazySubstring.boolValue); |
| 248 } else { | 245 } else { |
| 249 valueOrLazySubstring = | 246 valueOrLazySubstring = |
| 250 decodeUtf8(data, start, end, valueOrLazySubstring.boolValue); | 247 decodeUtf8(data, start, end, valueOrLazySubstring.boolValue); |
| 251 } | 248 } |
| 252 return valueOrLazySubstring; | 249 return valueOrLazySubstring; |
| 253 } | 250 } |
| 254 } | 251 } |
| 255 | 252 |
| 256 /// See [Token.stringValue] for an explanation. | 253 /// See [Token.stringValue] for an explanation. |
| 257 String get stringValue => null; | 254 String get stringValue => null; |
| 258 | 255 |
| 259 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN); | 256 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN); |
| 260 | 257 |
| 261 String toString() => "StringToken($value)"; | 258 String toString() => "StringToken($value)"; |
| 262 | 259 |
| 263 static final StringCanonicalizer canonicalizer = new StringCanonicalizer(); | 260 static final HashSet<String> canonicalizedSubstrings = new HashSet<String>(); |
| 264 | 261 |
| 265 static String canonicalizedString(String s, int start, int end, | 262 static String canonicalizedString(String s, bool canonicalize) { |
| 266 bool canonicalize) { | |
| 267 if (!canonicalize) return s; | 263 if (!canonicalize) return s; |
| 268 return canonicalizer.canonicalize(s, start, end, false); | 264 var result = canonicalizedSubstrings.lookup(s); |
| 265 if (result != null) return result; |
| 266 canonicalizedSubstrings.add(s); |
| 267 return s; |
| 269 } | 268 } |
| 270 | 269 |
| 271 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) { | 270 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) { |
| 272 return canonicalizer.canonicalize(data, start, end, asciiOnly); | 271 var s; |
| 272 if (asciiOnly) { |
| 273 s = new String.fromCharCodes(data, start, end); |
| 274 } else { |
| 275 s = UTF8.decoder.convert(data, start, end); |
| 276 } |
| 277 return canonicalizedString(s, true); |
| 273 } | 278 } |
| 274 } | 279 } |
| 275 | 280 |
| 276 /** | 281 /** |
| 277 * This class represents the necessary information to compute a substring | 282 * This class represents the necessary information to compute a substring |
| 278 * lazily. The substring can either originate from a string or from | 283 * lazily. The substring can either originate from a string or from |
| 279 * a [:List<int>:] of UTF-8 bytes. | 284 * a [:List<int>:] of UTF-8 bytes. |
| 280 */ | 285 */ |
| 281 abstract class LazySubstring { | 286 abstract class LazySubstring { |
| 282 /** The original data, either a string or a List<int> */ | 287 /** The original data, either a string or a List<int> */ |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 value == '<=' || | 367 value == '<=' || |
| 363 value == '<' || | 368 value == '<' || |
| 364 value == '&' || | 369 value == '&' || |
| 365 value == '^' || | 370 value == '^' || |
| 366 value == '|'; | 371 value == '|'; |
| 367 } | 372 } |
| 368 | 373 |
| 369 bool isTernaryOperator(String value) => value == '[]='; | 374 bool isTernaryOperator(String value) => value == '[]='; |
| 370 | 375 |
| 371 bool isMinusOperator(String value) => value == '-'; | 376 bool isMinusOperator(String value) => value == '-'; |
| OLD | NEW |