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