OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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 /** | 5 /** |
6 * Defines the tokens that are produced by the scanner, used by the parser, and | 6 * Defines the tokens that are produced by the scanner, used by the parser, and |
7 * referenced from the [AST structure](ast.dart). | 7 * referenced from the [AST structure](ast.dart). |
8 */ | 8 */ |
9 library analyzer.dart.ast.token; | 9 library analyzer.dart.ast.token; |
10 | 10 |
11 import 'dart:collection'; | 11 export 'package:front_end/src/scanner/token.dart' |
12 | 12 show Keyword, Token, TokenType; |
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 |