| 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 '../../scanner/token.dart' as analyzer; | 7 import '../../scanner/token.dart' as analyzer; |
| 8 import '../../scanner/token.dart' show TokenType; | 8 import '../../scanner/token.dart' show TokenType; |
| 9 | 9 |
| 10 import 'token_constants.dart' show IDENTIFIER_TOKEN; | 10 import 'token_constants.dart' show IDENTIFIER_TOKEN; |
| 11 | 11 |
| 12 import 'string_canonicalizer.dart'; | 12 import 'string_canonicalizer.dart'; |
| 13 | 13 |
| 14 /** | 14 /** |
| 15 * A token that doubles as a linked list. | 15 * A token that doubles as a linked list. |
| 16 */ | 16 */ |
| 17 abstract class Token implements analyzer.TokenWithComment { | 17 abstract class Token implements analyzer.TokenWithComment { |
| 18 /** | 18 @override |
| 19 * The character offset of the start of this token within the source text. | |
| 20 */ | |
| 21 int charOffset; | 19 int charOffset; |
| 22 | 20 |
| 23 Token(this.charOffset); | 21 Token(this.charOffset); |
| 24 | 22 |
| 25 /** | 23 /** |
| 26 * The next token in the token stream. | 24 * The next token in the token stream. |
| 27 */ | 25 */ |
| 28 Token next; | 26 Token next; |
| 29 | 27 |
| 30 /** | 28 /** |
| (...skipping 21 matching lines...) Expand all Loading... |
| 52 precedingCommentTokens = token; | 50 precedingCommentTokens = token; |
| 53 } | 51 } |
| 54 | 52 |
| 55 /** | 53 /** |
| 56 * The string represented by this token, a substring of the source code. | 54 * The string represented by this token, a substring of the source code. |
| 57 * | 55 * |
| 58 * For [StringToken]s the [lexeme] includes the quotes, explicit escapes, etc. | 56 * For [StringToken]s the [lexeme] includes the quotes, explicit escapes, etc. |
| 59 */ | 57 */ |
| 60 String get lexeme; | 58 String get lexeme; |
| 61 | 59 |
| 62 /** | 60 @override |
| 63 * For symbol and keyword tokens, returns the string value represented by this | 61 String get stringValue => type.stringValue; |
| 64 * token. For [StringToken]s this method returns [:null:]. | |
| 65 * | |
| 66 * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time | |
| 67 * constant originating in the [TokenType] or in the [Keyword] instance. | |
| 68 * This allows testing for keywords and symbols using [:identical:], e.g., | |
| 69 * [:identical('class', token.value):]. | |
| 70 * | |
| 71 * Note that returning [:null:] for string tokens is important to identify | |
| 72 * symbols and keywords, we cannot use [lexeme] instead. The string literal | |
| 73 * "$a($b" | |
| 74 * produces ..., SymbolToken($), StringToken(a), StringToken((), ... | |
| 75 * | |
| 76 * After parsing the identifier 'a', the parser tests for a function | |
| 77 * declaration using [:identical(next.stringValue, '('):], which (rightfully) | |
| 78 * returns false because stringValue returns [:null:]. | |
| 79 */ | |
| 80 String get stringValue; | |
| 81 | 62 |
| 82 /** | 63 /** |
| 83 * The kind enum of this token as determined by its [type]. | 64 * The kind enum of this token as determined by its [type]. |
| 84 */ | 65 */ |
| 85 int get kind => type.kind; | 66 int get kind => type.kind; |
| 86 | 67 |
| 87 /** | 68 /** |
| 88 * The precedence level for this token. | 69 * The precedence level for this token. |
| 89 */ | 70 */ |
| 90 int get precedence => type.precedence; | 71 int get precedence => type.precedence; |
| 91 | 72 |
| 92 /** | 73 /** |
| 93 * True if this token is an identifier. Some keywords allowed as identifiers, | 74 * True if this token is an identifier. Some keywords allowed as identifiers, |
| 94 * see implementation in [KeywordToken]. | 75 * see implementation in [KeywordToken]. |
| 95 */ | 76 */ |
| 96 bool get isIdentifier; | 77 bool get isIdentifier; |
| 97 | 78 |
| 98 bool get isPseudo => false; | 79 bool get isPseudo => false; |
| 99 | 80 |
| 100 /** | 81 /** |
| 101 * Returns a textual representation of this token to be used for debugging | 82 * Returns a textual representation of this token to be used for debugging |
| 102 * purposes. The resulting string might contain information about the | 83 * purposes. The resulting string might contain information about the |
| 103 * structure of the token, for example 'StringToken(foo)' for the identifier | 84 * structure of the token, for example 'StringToken(foo)' for the identifier |
| 104 * token 'foo'. | 85 * token 'foo'. |
| 105 * | 86 * |
| 106 * Use [lexeme] for the text actually parsed by the token. | 87 * Use [lexeme] for the text actually parsed by the token. |
| 107 */ | 88 */ |
| 108 String toString(); | 89 String toString(); |
| 109 | 90 |
| 110 /** | 91 @override |
| 111 * The number of characters parsed by this token. | |
| 112 */ | |
| 113 int get charCount { | 92 int get charCount { |
| 114 if (type == analyzer.TokenType.BAD_INPUT) { | 93 if (type == analyzer.TokenType.BAD_INPUT) { |
| 115 // This is a token that wraps around an error message. Return 1 | 94 // This is a token that wraps around an error message. Return 1 |
| 116 // instead of the size of the length of the error message. | 95 // instead of the size of the length of the error message. |
| 117 return 1; | 96 return 1; |
| 118 } else { | 97 } else { |
| 119 return lexeme.length; | 98 return lexeme.length; |
| 120 } | 99 } |
| 121 } | 100 } |
| 122 | 101 |
| 123 /// The character offset of the end of this token within the source text. | 102 @override |
| 124 int get charEnd => charOffset + charCount; | 103 int get charEnd => charOffset + charCount; |
| 125 | 104 |
| 126 bool get isEof => false; | 105 @override |
| 106 bool get isEof => type == analyzer.TokenType.EOF; |
| 127 | 107 |
| 128 bool get isBuiltInIdentifier => false; | 108 bool get isBuiltInIdentifier => false; |
| 129 | 109 |
| 130 @override | 110 @override |
| 131 bool get isOperator => type.isOperator; | 111 bool get isOperator => type.isOperator; |
| 132 | 112 |
| 133 @override | 113 @override |
| 134 bool get isUserDefinableOperator => type.isUserDefinableOperator; | 114 bool get isUserDefinableOperator => type.isUserDefinableOperator; |
| 135 | 115 |
| 136 @override | 116 @override |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 // EOF points to itself so there's always infinite look-ahead. | 216 // EOF points to itself so there's always infinite look-ahead. |
| 237 eof.previousToken = eof; | 217 eof.previousToken = eof; |
| 238 eof.next = eof; | 218 eof.next = eof; |
| 239 return eof; | 219 return eof; |
| 240 } | 220 } |
| 241 | 221 |
| 242 @override | 222 @override |
| 243 String get lexeme => type.value; | 223 String get lexeme => type.value; |
| 244 | 224 |
| 245 @override | 225 @override |
| 246 String get stringValue => type.value; | |
| 247 | |
| 248 @override | |
| 249 bool get isIdentifier => false; | 226 bool get isIdentifier => false; |
| 250 | 227 |
| 251 @override | 228 @override |
| 252 String toString() => "SymbolToken(${isEof ? '-eof-' : lexeme})"; | 229 String toString() => "SymbolToken(${isEof ? '-eof-' : lexeme})"; |
| 253 | 230 |
| 254 @override | 231 @override |
| 255 bool get isEof => type == analyzer.TokenType.EOF; | |
| 256 | |
| 257 @override | |
| 258 Token copyWithoutComments() => isEof | 232 Token copyWithoutComments() => isEof |
| 259 ? new SymbolToken.eof(charOffset) | 233 ? new SymbolToken.eof(charOffset) |
| 260 : new SymbolToken(type, charOffset); | 234 : new SymbolToken(type, charOffset); |
| 261 } | 235 } |
| 262 | 236 |
| 263 /** | 237 /** |
| 264 * A [SyntheticSymbolToken] represents the symbol in its precedence info | 238 * A [SyntheticSymbolToken] represents the symbol in its precedence info |
| 265 * which does not exist in the original source. | 239 * which does not exist in the original source. |
| 266 * For example, if the scanner finds '(' missing a ')' | 240 * For example, if the scanner finds '(' missing a ')' |
| 267 * then it will insert an synthetic ')'. | 241 * then it will insert an synthetic ')'. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 */ | 285 */ |
| 312 class KeywordToken extends Token implements analyzer.KeywordTokenWithComment { | 286 class KeywordToken extends Token implements analyzer.KeywordTokenWithComment { |
| 313 final analyzer.Keyword keyword; | 287 final analyzer.Keyword keyword; |
| 314 | 288 |
| 315 KeywordToken(this.keyword, int charOffset) : super(charOffset); | 289 KeywordToken(this.keyword, int charOffset) : super(charOffset); |
| 316 | 290 |
| 317 TokenType get info => keyword; | 291 TokenType get info => keyword; |
| 318 | 292 |
| 319 String get lexeme => keyword.lexeme; | 293 String get lexeme => keyword.lexeme; |
| 320 | 294 |
| 321 String get stringValue => keyword.lexeme; | |
| 322 | |
| 323 bool get isIdentifier => keyword.isPseudo || keyword.isBuiltIn; | 295 bool get isIdentifier => keyword.isPseudo || keyword.isBuiltIn; |
| 324 | 296 |
| 325 bool get isPseudo => keyword.isPseudo; | 297 bool get isPseudo => keyword.isPseudo; |
| 326 | 298 |
| 327 bool get isBuiltInIdentifier => keyword.isBuiltIn; | 299 bool get isBuiltInIdentifier => keyword.isBuiltIn; |
| 328 | 300 |
| 329 String toString() => "KeywordToken($lexeme)"; | 301 String toString() => "KeywordToken($lexeme)"; |
| 330 | 302 |
| 331 @override | 303 @override |
| 332 Token copyWithoutComments() => new KeywordToken(keyword, charOffset); | 304 Token copyWithoutComments() => new KeywordToken(keyword, charOffset); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 valueOrLazySubstring = canonicalizedString( | 410 valueOrLazySubstring = canonicalizedString( |
| 439 data, start, end, valueOrLazySubstring.boolValue); | 411 data, start, end, valueOrLazySubstring.boolValue); |
| 440 } else { | 412 } else { |
| 441 valueOrLazySubstring = | 413 valueOrLazySubstring = |
| 442 decodeUtf8(data, start, end, valueOrLazySubstring.boolValue); | 414 decodeUtf8(data, start, end, valueOrLazySubstring.boolValue); |
| 443 } | 415 } |
| 444 return valueOrLazySubstring; | 416 return valueOrLazySubstring; |
| 445 } | 417 } |
| 446 } | 418 } |
| 447 | 419 |
| 448 /// See [Token.stringValue] for an explanation. | |
| 449 String get stringValue => null; | |
| 450 | |
| 451 bool get isIdentifier => identical(kind, IDENTIFIER_TOKEN); | 420 bool get isIdentifier => identical(kind, IDENTIFIER_TOKEN); |
| 452 | 421 |
| 453 String toString() => "StringToken($lexeme)"; | 422 String toString() => "StringToken($lexeme)"; |
| 454 | 423 |
| 455 static final StringCanonicalizer canonicalizer = new StringCanonicalizer(); | 424 static final StringCanonicalizer canonicalizer = new StringCanonicalizer(); |
| 456 | 425 |
| 457 static String canonicalizedString( | 426 static String canonicalizedString( |
| 458 String s, int start, int end, bool canonicalize) { | 427 String s, int start, int end, bool canonicalize) { |
| 459 if (!canonicalize) return s; | 428 if (!canonicalize) return s; |
| 460 return canonicalizer.canonicalize(s, start, end, false); | 429 return canonicalizer.canonicalize(s, start, end, false); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 identical(value, "<=") || | 635 identical(value, "<=") || |
| 667 identical(value, "<") || | 636 identical(value, "<") || |
| 668 identical(value, "&") || | 637 identical(value, "&") || |
| 669 identical(value, "^") || | 638 identical(value, "^") || |
| 670 identical(value, "|"); | 639 identical(value, "|"); |
| 671 } | 640 } |
| 672 | 641 |
| 673 bool isTernaryOperator(String value) => identical(value, "[]="); | 642 bool isTernaryOperator(String value) => identical(value, "[]="); |
| 674 | 643 |
| 675 bool isMinusOperator(String value) => identical(value, "-"); | 644 bool isMinusOperator(String value) => identical(value, "-"); |
| OLD | NEW |