OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 /** |
| 6 * Defines the tokens that are produced by the scanner, used by the parser, and |
| 7 * referenced from the [AST structure](ast.dart). |
| 8 */ |
| 9 library analyzer.dart.ast.token; |
| 10 |
| 11 import 'dart:collection'; |
| 12 |
| 13 import 'package:analyzer/src/dart/ast/token.dart' show SimpleToken, TokenClass; |
| 14 |
| 15 /** |
| 16 * The keywords in the Dart programming language. |
| 17 * |
| 18 * Clients may not extend, implement or mix-in this class. |
| 19 */ |
| 20 class Keyword { |
| 21 static const Keyword ABSTRACT = const Keyword._('ABSTRACT', "abstract", true); |
| 22 |
| 23 static const Keyword AS = const Keyword._('AS', "as", true); |
| 24 |
| 25 static const Keyword ASSERT = const Keyword._('ASSERT', "assert"); |
| 26 |
| 27 static const Keyword BREAK = const Keyword._('BREAK', "break"); |
| 28 |
| 29 static const Keyword CASE = const Keyword._('CASE', "case"); |
| 30 |
| 31 static const Keyword CATCH = const Keyword._('CATCH', "catch"); |
| 32 |
| 33 static const Keyword CLASS = const Keyword._('CLASS', "class"); |
| 34 |
| 35 static const Keyword CONST = const Keyword._('CONST', "const"); |
| 36 |
| 37 static const Keyword CONTINUE = const Keyword._('CONTINUE', "continue"); |
| 38 |
| 39 static const Keyword DEFAULT = const Keyword._('DEFAULT', "default"); |
| 40 |
| 41 static const Keyword DEFERRED = const Keyword._('DEFERRED', "deferred", true); |
| 42 |
| 43 static const Keyword DO = const Keyword._('DO', "do"); |
| 44 |
| 45 static const Keyword DYNAMIC = const Keyword._('DYNAMIC', "dynamic", true); |
| 46 |
| 47 static const Keyword ELSE = const Keyword._('ELSE', "else"); |
| 48 |
| 49 static const Keyword ENUM = const Keyword._('ENUM', "enum"); |
| 50 |
| 51 static const Keyword EXPORT = const Keyword._('EXPORT', "export", true); |
| 52 |
| 53 static const Keyword EXTENDS = const Keyword._('EXTENDS', "extends"); |
| 54 |
| 55 static const Keyword EXTERNAL = const Keyword._('EXTERNAL', "external", true); |
| 56 |
| 57 static const Keyword FACTORY = const Keyword._('FACTORY', "factory", true); |
| 58 |
| 59 static const Keyword FALSE = const Keyword._('FALSE', "false"); |
| 60 |
| 61 static const Keyword FINAL = const Keyword._('FINAL', "final"); |
| 62 |
| 63 static const Keyword FINALLY = const Keyword._('FINALLY', "finally"); |
| 64 |
| 65 static const Keyword FOR = const Keyword._('FOR', "for"); |
| 66 |
| 67 static const Keyword GET = const Keyword._('GET', "get", true); |
| 68 |
| 69 static const Keyword IF = const Keyword._('IF', "if"); |
| 70 |
| 71 static const Keyword IMPLEMENTS = |
| 72 const Keyword._('IMPLEMENTS', "implements", true); |
| 73 |
| 74 static const Keyword IMPORT = const Keyword._('IMPORT', "import", true); |
| 75 |
| 76 static const Keyword IN = const Keyword._('IN', "in"); |
| 77 |
| 78 static const Keyword IS = const Keyword._('IS', "is"); |
| 79 |
| 80 static const Keyword LIBRARY = const Keyword._('LIBRARY', "library", true); |
| 81 |
| 82 static const Keyword NEW = const Keyword._('NEW', "new"); |
| 83 |
| 84 static const Keyword NULL = const Keyword._('NULL', "null"); |
| 85 |
| 86 static const Keyword OPERATOR = const Keyword._('OPERATOR', "operator", true); |
| 87 |
| 88 static const Keyword PART = const Keyword._('PART', "part", true); |
| 89 |
| 90 static const Keyword RETHROW = const Keyword._('RETHROW', "rethrow"); |
| 91 |
| 92 static const Keyword RETURN = const Keyword._('RETURN', "return"); |
| 93 |
| 94 static const Keyword SET = const Keyword._('SET', "set", true); |
| 95 |
| 96 static const Keyword STATIC = const Keyword._('STATIC', "static", true); |
| 97 |
| 98 static const Keyword SUPER = const Keyword._('SUPER', "super"); |
| 99 |
| 100 static const Keyword SWITCH = const Keyword._('SWITCH', "switch"); |
| 101 |
| 102 static const Keyword THIS = const Keyword._('THIS', "this"); |
| 103 |
| 104 static const Keyword THROW = const Keyword._('THROW', "throw"); |
| 105 |
| 106 static const Keyword TRUE = const Keyword._('TRUE', "true"); |
| 107 |
| 108 static const Keyword TRY = const Keyword._('TRY', "try"); |
| 109 |
| 110 static const Keyword TYPEDEF = const Keyword._('TYPEDEF', "typedef", true); |
| 111 |
| 112 static const Keyword VAR = const Keyword._('VAR', "var"); |
| 113 |
| 114 static const Keyword VOID = const Keyword._('VOID', "void"); |
| 115 |
| 116 static const Keyword WHILE = const Keyword._('WHILE', "while"); |
| 117 |
| 118 static const Keyword WITH = const Keyword._('WITH', "with"); |
| 119 |
| 120 static const List<Keyword> values = const <Keyword>[ |
| 121 ABSTRACT, |
| 122 AS, |
| 123 ASSERT, |
| 124 BREAK, |
| 125 CASE, |
| 126 CATCH, |
| 127 CLASS, |
| 128 CONST, |
| 129 CONTINUE, |
| 130 DEFAULT, |
| 131 DEFERRED, |
| 132 DO, |
| 133 DYNAMIC, |
| 134 ELSE, |
| 135 ENUM, |
| 136 EXPORT, |
| 137 EXTENDS, |
| 138 EXTERNAL, |
| 139 FACTORY, |
| 140 FALSE, |
| 141 FINAL, |
| 142 FINALLY, |
| 143 FOR, |
| 144 GET, |
| 145 IF, |
| 146 IMPLEMENTS, |
| 147 IMPORT, |
| 148 IN, |
| 149 IS, |
| 150 LIBRARY, |
| 151 NEW, |
| 152 NULL, |
| 153 OPERATOR, |
| 154 PART, |
| 155 RETHROW, |
| 156 RETURN, |
| 157 SET, |
| 158 STATIC, |
| 159 SUPER, |
| 160 SWITCH, |
| 161 THIS, |
| 162 THROW, |
| 163 TRUE, |
| 164 TRY, |
| 165 TYPEDEF, |
| 166 VAR, |
| 167 VOID, |
| 168 WHILE, |
| 169 WITH, |
| 170 ]; |
| 171 |
| 172 /** |
| 173 * A table mapping the lexemes of keywords to the corresponding keyword. |
| 174 */ |
| 175 static final Map<String, Keyword> keywords = _createKeywordMap(); |
| 176 |
| 177 /** |
| 178 * The name of the keyword type. |
| 179 */ |
| 180 final String name; |
| 181 |
| 182 /** |
| 183 * The lexeme for the keyword. |
| 184 */ |
| 185 final String syntax; |
| 186 |
| 187 /** |
| 188 * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords |
| 189 * can be used as identifiers. |
| 190 */ |
| 191 final bool isPseudoKeyword; |
| 192 |
| 193 /** |
| 194 * Initialize a newly created keyword to have the given [name] and [syntax]. |
| 195 * The keyword is a pseudo-keyword if the [isPseudoKeyword] flag is `true`. |
| 196 */ |
| 197 const Keyword._(this.name, this.syntax, [this.isPseudoKeyword = false]); |
| 198 |
| 199 @override |
| 200 String toString() => name; |
| 201 |
| 202 /** |
| 203 * Create a table mapping the lexemes of keywords to the corresponding keyword |
| 204 * and return the table that was created. |
| 205 */ |
| 206 static Map<String, Keyword> _createKeywordMap() { |
| 207 LinkedHashMap<String, Keyword> result = |
| 208 new LinkedHashMap<String, Keyword>(); |
| 209 for (Keyword keyword in values) { |
| 210 result[keyword.syntax] = keyword; |
| 211 } |
| 212 return result; |
| 213 } |
| 214 } |
| 215 |
| 216 /** |
| 217 * A token that was scanned from the input. Each token knows which tokens |
| 218 * precede and follow it, acting as a link in a doubly linked list of tokens. |
| 219 * |
| 220 * Clients may not extend, implement or mix-in this class. |
| 221 */ |
| 222 abstract class Token { |
| 223 /** |
| 224 * Initialize a newly created token to have the given [type] and [offset]. |
| 225 */ |
| 226 factory Token(TokenType type, int offset) = SimpleToken; |
| 227 |
| 228 /** |
| 229 * Return the offset from the beginning of the file to the character after the |
| 230 * last character of the token. |
| 231 */ |
| 232 int get end; |
| 233 |
| 234 /** |
| 235 * Return `true` if this token represents an operator. |
| 236 */ |
| 237 bool get isOperator; |
| 238 |
| 239 /** |
| 240 * Return `true` if this token is a synthetic token. A synthetic token is a |
| 241 * token that was introduced by the parser in order to recover from an error |
| 242 * in the code. |
| 243 */ |
| 244 bool get isSynthetic; |
| 245 |
| 246 /** |
| 247 * Return `true` if this token represents an operator that can be defined by |
| 248 * users. |
| 249 */ |
| 250 bool get isUserDefinableOperator; |
| 251 |
| 252 /** |
| 253 * Return the number of characters in the node's source range. |
| 254 */ |
| 255 int get length; |
| 256 |
| 257 /** |
| 258 * Return the lexeme that represents this token. |
| 259 */ |
| 260 String get lexeme; |
| 261 |
| 262 /** |
| 263 * Return the next token in the token stream. |
| 264 */ |
| 265 Token get next; |
| 266 |
| 267 /** |
| 268 * Return the offset from the beginning of the file to the first character in |
| 269 * the token. |
| 270 */ |
| 271 int get offset; |
| 272 |
| 273 /** |
| 274 * Set the offset from the beginning of the file to the first character in |
| 275 * the token to the given [offset]. |
| 276 */ |
| 277 void set offset(int offset); |
| 278 |
| 279 /** |
| 280 * Return the first comment in the list of comments that precede this token, |
| 281 * or `null` if there are no comments preceding this token. Additional |
| 282 * comments can be reached by following the token stream using [next] until |
| 283 * `null` is returned. |
| 284 * |
| 285 * For example, if the original contents were `/* one */ /* two */ id`, then |
| 286 * the first preceding comment token will have a lexeme of `/* one */` and |
| 287 * the next comment token will have a lexeme of `/* two */`. |
| 288 */ |
| 289 Token get precedingComments; |
| 290 |
| 291 /** |
| 292 * Return the previous token in the token stream. |
| 293 */ |
| 294 Token get previous; |
| 295 |
| 296 /** |
| 297 * Set the previous token in the token stream to the given [token]. |
| 298 */ |
| 299 void set previous(Token token); |
| 300 |
| 301 /** |
| 302 * Return the type of the token. |
| 303 */ |
| 304 TokenType get type; |
| 305 |
| 306 /** |
| 307 * Apply (add) the given [delta] to this token's offset. |
| 308 */ |
| 309 void applyDelta(int delta); |
| 310 |
| 311 /** |
| 312 * Return a newly created token that is a copy of this token but that is not a |
| 313 * part of any token stream. |
| 314 */ |
| 315 Token copy(); |
| 316 |
| 317 /** |
| 318 * Copy a linked list of comment tokens identical to the given comment tokens. |
| 319 */ |
| 320 Token copyComments(Token token); |
| 321 |
| 322 /** |
| 323 * Return `true` if this token has any one of the given [types]. |
| 324 */ |
| 325 bool matchesAny(List<TokenType> types); |
| 326 |
| 327 /** |
| 328 * Set the next token in the token stream to the given [token]. This has the |
| 329 * side-effect of setting this token to be the previous token for the given |
| 330 * token. Return the token that was passed in. |
| 331 */ |
| 332 Token setNext(Token token); |
| 333 |
| 334 /** |
| 335 * Set the next token in the token stream to the given token without changing |
| 336 * which token is the previous token for the given token. Return the token |
| 337 * that was passed in. |
| 338 */ |
| 339 Token setNextWithoutSettingPrevious(Token token); |
| 340 |
| 341 /** |
| 342 * Return the value of this token. For keyword tokens, this is the keyword |
| 343 * associated with the token, for other tokens it is the lexeme associated |
| 344 * with the token. |
| 345 */ |
| 346 Object value(); |
| 347 |
| 348 /** |
| 349 * Compare the given [tokens] to find the token that appears first in the |
| 350 * source being parsed. That is, return the left-most of all of the tokens. |
| 351 * The list must be non-`null`, but the elements of the list are allowed to be |
| 352 * `null`. Return the token with the smallest offset, or `null` if the list is |
| 353 * empty or if all of the elements of the list are `null`. |
| 354 */ |
| 355 static Token lexicallyFirst(List<Token> tokens) { |
| 356 Token first = null; |
| 357 int offset = -1; |
| 358 for (Token token in tokens) { |
| 359 if (token != null && (offset < 0 || token.offset < offset)) { |
| 360 first = token; |
| 361 offset = token.offset; |
| 362 } |
| 363 } |
| 364 return first; |
| 365 } |
| 366 } |
| 367 |
| 368 /** |
| 369 * The types of tokens that can be returned by the scanner. |
| 370 */ |
| 371 class TokenType { |
| 372 /** |
| 373 * The type of the token that marks the end of the input. |
| 374 */ |
| 375 static const TokenType EOF = const _EndOfFileTokenType(); |
| 376 |
| 377 static const TokenType DOUBLE = const TokenType._('DOUBLE'); |
| 378 |
| 379 static const TokenType HEXADECIMAL = const TokenType._('HEXADECIMAL'); |
| 380 |
| 381 static const TokenType IDENTIFIER = const TokenType._('IDENTIFIER'); |
| 382 |
| 383 static const TokenType INT = const TokenType._('INT'); |
| 384 |
| 385 static const TokenType KEYWORD = const TokenType._('KEYWORD'); |
| 386 |
| 387 static const TokenType MULTI_LINE_COMMENT = |
| 388 const TokenType._('MULTI_LINE_COMMENT'); |
| 389 |
| 390 static const TokenType SCRIPT_TAG = const TokenType._('SCRIPT_TAG'); |
| 391 |
| 392 static const TokenType SINGLE_LINE_COMMENT = |
| 393 const TokenType._('SINGLE_LINE_COMMENT'); |
| 394 |
| 395 static const TokenType STRING = const TokenType._('STRING'); |
| 396 |
| 397 static const TokenType AMPERSAND = |
| 398 const TokenType._('AMPERSAND', TokenClass.BITWISE_AND_OPERATOR, '&'); |
| 399 |
| 400 static const TokenType AMPERSAND_AMPERSAND = const TokenType._( |
| 401 'AMPERSAND_AMPERSAND', TokenClass.LOGICAL_AND_OPERATOR, '&&'); |
| 402 |
| 403 static const TokenType AMPERSAND_EQ = |
| 404 const TokenType._('AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, '&='); |
| 405 |
| 406 static const TokenType AT = const TokenType._('AT', TokenClass.NO_CLASS, '@'); |
| 407 |
| 408 static const TokenType BANG = |
| 409 const TokenType._('BANG', TokenClass.UNARY_PREFIX_OPERATOR, '!'); |
| 410 |
| 411 static const TokenType BANG_EQ = |
| 412 const TokenType._('BANG_EQ', TokenClass.EQUALITY_OPERATOR, '!='); |
| 413 |
| 414 static const TokenType BAR = |
| 415 const TokenType._('BAR', TokenClass.BITWISE_OR_OPERATOR, '|'); |
| 416 |
| 417 static const TokenType BAR_BAR = |
| 418 const TokenType._('BAR_BAR', TokenClass.LOGICAL_OR_OPERATOR, '||'); |
| 419 |
| 420 static const TokenType BAR_EQ = |
| 421 const TokenType._('BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, '|='); |
| 422 |
| 423 static const TokenType COLON = |
| 424 const TokenType._('COLON', TokenClass.NO_CLASS, ':'); |
| 425 |
| 426 static const TokenType COMMA = |
| 427 const TokenType._('COMMA', TokenClass.NO_CLASS, ','); |
| 428 |
| 429 static const TokenType CARET = |
| 430 const TokenType._('CARET', TokenClass.BITWISE_XOR_OPERATOR, '^'); |
| 431 |
| 432 static const TokenType CARET_EQ = |
| 433 const TokenType._('CARET_EQ', TokenClass.ASSIGNMENT_OPERATOR, '^='); |
| 434 |
| 435 static const TokenType CLOSE_CURLY_BRACKET = |
| 436 const TokenType._('CLOSE_CURLY_BRACKET', TokenClass.NO_CLASS, '}'); |
| 437 |
| 438 static const TokenType CLOSE_PAREN = |
| 439 const TokenType._('CLOSE_PAREN', TokenClass.NO_CLASS, ')'); |
| 440 |
| 441 static const TokenType CLOSE_SQUARE_BRACKET = |
| 442 const TokenType._('CLOSE_SQUARE_BRACKET', TokenClass.NO_CLASS, ']'); |
| 443 |
| 444 static const TokenType EQ = |
| 445 const TokenType._('EQ', TokenClass.ASSIGNMENT_OPERATOR, '='); |
| 446 |
| 447 static const TokenType EQ_EQ = |
| 448 const TokenType._('EQ_EQ', TokenClass.EQUALITY_OPERATOR, '=='); |
| 449 |
| 450 static const TokenType FUNCTION = |
| 451 const TokenType._('FUNCTION', TokenClass.NO_CLASS, '=>'); |
| 452 |
| 453 static const TokenType GT = |
| 454 const TokenType._('GT', TokenClass.RELATIONAL_OPERATOR, '>'); |
| 455 |
| 456 static const TokenType GT_EQ = |
| 457 const TokenType._('GT_EQ', TokenClass.RELATIONAL_OPERATOR, '>='); |
| 458 |
| 459 static const TokenType GT_GT = |
| 460 const TokenType._('GT_GT', TokenClass.SHIFT_OPERATOR, '>>'); |
| 461 |
| 462 static const TokenType GT_GT_EQ = |
| 463 const TokenType._('GT_GT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '>>='); |
| 464 |
| 465 static const TokenType HASH = |
| 466 const TokenType._('HASH', TokenClass.NO_CLASS, '#'); |
| 467 |
| 468 static const TokenType INDEX = |
| 469 const TokenType._('INDEX', TokenClass.UNARY_POSTFIX_OPERATOR, '[]'); |
| 470 |
| 471 static const TokenType INDEX_EQ = |
| 472 const TokenType._('INDEX_EQ', TokenClass.UNARY_POSTFIX_OPERATOR, '[]='); |
| 473 |
| 474 static const TokenType IS = |
| 475 const TokenType._('IS', TokenClass.RELATIONAL_OPERATOR, 'is'); |
| 476 |
| 477 static const TokenType LT = |
| 478 const TokenType._('LT', TokenClass.RELATIONAL_OPERATOR, '<'); |
| 479 |
| 480 static const TokenType LT_EQ = |
| 481 const TokenType._('LT_EQ', TokenClass.RELATIONAL_OPERATOR, '<='); |
| 482 |
| 483 static const TokenType LT_LT = |
| 484 const TokenType._('LT_LT', TokenClass.SHIFT_OPERATOR, '<<'); |
| 485 |
| 486 static const TokenType LT_LT_EQ = |
| 487 const TokenType._('LT_LT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '<<='); |
| 488 |
| 489 static const TokenType MINUS = |
| 490 const TokenType._('MINUS', TokenClass.ADDITIVE_OPERATOR, '-'); |
| 491 |
| 492 static const TokenType MINUS_EQ = |
| 493 const TokenType._('MINUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, '-='); |
| 494 |
| 495 static const TokenType MINUS_MINUS = |
| 496 const TokenType._('MINUS_MINUS', TokenClass.UNARY_PREFIX_OPERATOR, '--'); |
| 497 |
| 498 static const TokenType OPEN_CURLY_BRACKET = |
| 499 const TokenType._('OPEN_CURLY_BRACKET', TokenClass.NO_CLASS, '{'); |
| 500 |
| 501 static const TokenType OPEN_PAREN = |
| 502 const TokenType._('OPEN_PAREN', TokenClass.UNARY_POSTFIX_OPERATOR, '('); |
| 503 |
| 504 static const TokenType OPEN_SQUARE_BRACKET = const TokenType._( |
| 505 'OPEN_SQUARE_BRACKET', TokenClass.UNARY_POSTFIX_OPERATOR, '['); |
| 506 |
| 507 static const TokenType PERCENT = |
| 508 const TokenType._('PERCENT', TokenClass.MULTIPLICATIVE_OPERATOR, '%'); |
| 509 |
| 510 static const TokenType PERCENT_EQ = |
| 511 const TokenType._('PERCENT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '%='); |
| 512 |
| 513 static const TokenType PERIOD = |
| 514 const TokenType._('PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '.'); |
| 515 |
| 516 static const TokenType PERIOD_PERIOD = |
| 517 const TokenType._('PERIOD_PERIOD', TokenClass.CASCADE_OPERATOR, '..'); |
| 518 |
| 519 static const TokenType PLUS = |
| 520 const TokenType._('PLUS', TokenClass.ADDITIVE_OPERATOR, '+'); |
| 521 |
| 522 static const TokenType PLUS_EQ = |
| 523 const TokenType._('PLUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, '+='); |
| 524 |
| 525 static const TokenType PLUS_PLUS = |
| 526 const TokenType._('PLUS_PLUS', TokenClass.UNARY_PREFIX_OPERATOR, '++'); |
| 527 |
| 528 static const TokenType QUESTION = |
| 529 const TokenType._('QUESTION', TokenClass.CONDITIONAL_OPERATOR, '?'); |
| 530 |
| 531 static const TokenType QUESTION_PERIOD = const TokenType._( |
| 532 'QUESTION_PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '?.'); |
| 533 |
| 534 static const TokenType QUESTION_QUESTION = |
| 535 const TokenType._('QUESTION_QUESTION', TokenClass.IF_NULL_OPERATOR, '??'); |
| 536 |
| 537 static const TokenType QUESTION_QUESTION_EQ = const TokenType._( |
| 538 'QUESTION_QUESTION_EQ', TokenClass.ASSIGNMENT_OPERATOR, '??='); |
| 539 |
| 540 static const TokenType SEMICOLON = |
| 541 const TokenType._('SEMICOLON', TokenClass.NO_CLASS, ';'); |
| 542 |
| 543 static const TokenType SLASH = |
| 544 const TokenType._('SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, '/'); |
| 545 |
| 546 static const TokenType SLASH_EQ = |
| 547 const TokenType._('SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, '/='); |
| 548 |
| 549 static const TokenType STAR = |
| 550 const TokenType._('STAR', TokenClass.MULTIPLICATIVE_OPERATOR, '*'); |
| 551 |
| 552 static const TokenType STAR_EQ = |
| 553 const TokenType._('STAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "*="); |
| 554 |
| 555 static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType._( |
| 556 'STRING_INTERPOLATION_EXPRESSION', TokenClass.NO_CLASS, '\${'); |
| 557 |
| 558 static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType._( |
| 559 'STRING_INTERPOLATION_IDENTIFIER', TokenClass.NO_CLASS, '\$'); |
| 560 |
| 561 static const TokenType TILDE = |
| 562 const TokenType._('TILDE', TokenClass.UNARY_PREFIX_OPERATOR, '~'); |
| 563 |
| 564 static const TokenType TILDE_SLASH = const TokenType._( |
| 565 'TILDE_SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, '~/'); |
| 566 |
| 567 static const TokenType TILDE_SLASH_EQ = const TokenType._( |
| 568 'TILDE_SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, '~/='); |
| 569 |
| 570 static const TokenType BACKPING = |
| 571 const TokenType._('BACKPING', TokenClass.NO_CLASS, '`'); |
| 572 |
| 573 static const TokenType BACKSLASH = |
| 574 const TokenType._('BACKSLASH', TokenClass.NO_CLASS, '\\'); |
| 575 |
| 576 static const TokenType PERIOD_PERIOD_PERIOD = |
| 577 const TokenType._('PERIOD_PERIOD_PERIOD', TokenClass.NO_CLASS, '...'); |
| 578 |
| 579 static const TokenType GENERIC_METHOD_TYPE_LIST = |
| 580 const TokenType._('GENERIC_METHOD_TYPE_LIST'); |
| 581 |
| 582 static const TokenType GENERIC_METHOD_TYPE_ASSIGN = |
| 583 const TokenType._('GENERIC_METHOD_TYPE_ASSIGN'); |
| 584 |
| 585 /** |
| 586 * The class of the token. |
| 587 */ |
| 588 final TokenClass _tokenClass; |
| 589 |
| 590 /** |
| 591 * The name of the token type. |
| 592 */ |
| 593 final String name; |
| 594 |
| 595 /** |
| 596 * The lexeme that defines this type of token, or `null` if there is more than |
| 597 * one possible lexeme for this type of token. |
| 598 */ |
| 599 final String lexeme; |
| 600 |
| 601 const TokenType._(this.name, |
| 602 [this._tokenClass = TokenClass.NO_CLASS, this.lexeme = null]); |
| 603 |
| 604 /** |
| 605 * Return `true` if this type of token represents an additive operator. |
| 606 */ |
| 607 bool get isAdditiveOperator => _tokenClass == TokenClass.ADDITIVE_OPERATOR; |
| 608 |
| 609 /** |
| 610 * Return `true` if this type of token represents an assignment operator. |
| 611 */ |
| 612 bool get isAssignmentOperator => |
| 613 _tokenClass == TokenClass.ASSIGNMENT_OPERATOR; |
| 614 |
| 615 /** |
| 616 * Return `true` if this type of token represents an associative operator. An |
| 617 * associative operator is an operator for which the following equality is |
| 618 * true: `(a * b) * c == a * (b * c)`. In other words, if the result of |
| 619 * applying the operator to multiple operands does not depend on the order in |
| 620 * which those applications occur. |
| 621 * |
| 622 * Note: This method considers the logical-and and logical-or operators to be |
| 623 * associative, even though the order in which the application of those |
| 624 * operators can have an effect because evaluation of the right-hand operand |
| 625 * is conditional. |
| 626 */ |
| 627 bool get isAssociativeOperator => |
| 628 this == AMPERSAND || |
| 629 this == AMPERSAND_AMPERSAND || |
| 630 this == BAR || |
| 631 this == BAR_BAR || |
| 632 this == CARET || |
| 633 this == PLUS || |
| 634 this == STAR; |
| 635 |
| 636 /** |
| 637 * Return `true` if this type of token represents an equality operator. |
| 638 */ |
| 639 bool get isEqualityOperator => _tokenClass == TokenClass.EQUALITY_OPERATOR; |
| 640 |
| 641 /** |
| 642 * Return `true` if this type of token represents an increment operator. |
| 643 */ |
| 644 bool get isIncrementOperator => |
| 645 identical(lexeme, '++') || identical(lexeme, '--'); |
| 646 |
| 647 /** |
| 648 * Return `true` if this type of token represents a multiplicative operator. |
| 649 */ |
| 650 bool get isMultiplicativeOperator => |
| 651 _tokenClass == TokenClass.MULTIPLICATIVE_OPERATOR; |
| 652 |
| 653 /** |
| 654 * Return `true` if this token type represents an operator. |
| 655 */ |
| 656 bool get isOperator => |
| 657 _tokenClass != TokenClass.NO_CLASS && |
| 658 this != OPEN_PAREN && |
| 659 this != OPEN_SQUARE_BRACKET && |
| 660 this != PERIOD; |
| 661 |
| 662 /** |
| 663 * Return `true` if this type of token represents a relational operator. |
| 664 */ |
| 665 bool get isRelationalOperator => |
| 666 _tokenClass == TokenClass.RELATIONAL_OPERATOR; |
| 667 |
| 668 /** |
| 669 * Return `true` if this type of token represents a shift operator. |
| 670 */ |
| 671 bool get isShiftOperator => _tokenClass == TokenClass.SHIFT_OPERATOR; |
| 672 |
| 673 /** |
| 674 * Return `true` if this type of token represents a unary postfix operator. |
| 675 */ |
| 676 bool get isUnaryPostfixOperator => |
| 677 _tokenClass == TokenClass.UNARY_POSTFIX_OPERATOR; |
| 678 |
| 679 /** |
| 680 * Return `true` if this type of token represents a unary prefix operator. |
| 681 */ |
| 682 bool get isUnaryPrefixOperator => |
| 683 _tokenClass == TokenClass.UNARY_PREFIX_OPERATOR; |
| 684 |
| 685 /** |
| 686 * Return `true` if this token type represents an operator that can be defined |
| 687 * by users. |
| 688 */ |
| 689 bool get isUserDefinableOperator => |
| 690 identical(lexeme, '==') || |
| 691 identical(lexeme, '~') || |
| 692 identical(lexeme, '[]') || |
| 693 identical(lexeme, '[]=') || |
| 694 identical(lexeme, '*') || |
| 695 identical(lexeme, '/') || |
| 696 identical(lexeme, '%') || |
| 697 identical(lexeme, '~/') || |
| 698 identical(lexeme, '+') || |
| 699 identical(lexeme, '-') || |
| 700 identical(lexeme, '<<') || |
| 701 identical(lexeme, '>>') || |
| 702 identical(lexeme, '>=') || |
| 703 identical(lexeme, '>') || |
| 704 identical(lexeme, '<=') || |
| 705 identical(lexeme, '<') || |
| 706 identical(lexeme, '&') || |
| 707 identical(lexeme, '^') || |
| 708 identical(lexeme, '|'); |
| 709 |
| 710 /** |
| 711 * Return the precedence of the token, or `0` if the token does not represent |
| 712 * an operator. |
| 713 */ |
| 714 int get precedence => _tokenClass.precedence; |
| 715 |
| 716 @override |
| 717 String toString() => name; |
| 718 } |
| 719 |
| 720 /** |
| 721 * A token representing the end (either the head or the tail) of a stream of |
| 722 * tokens. |
| 723 */ |
| 724 class _EndOfFileTokenType extends TokenType { |
| 725 /** |
| 726 * Initialize a newly created token. |
| 727 */ |
| 728 const _EndOfFileTokenType() : super._('EOF', TokenClass.NO_CLASS, ''); |
| 729 |
| 730 @override |
| 731 String toString() => '-eof-'; |
| 732 } |
OLD | NEW |