Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(826)

Side by Side Diff: pkg/analyzer/lib/src/generated/scanner.dart

Issue 1690523002: Move Token into the public API (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analyzer/lib/src/dart/ast/token.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 library analyzer.src.generated.scanner; 5 library analyzer.src.generated.scanner;
6 6
7 import 'dart:collection'; 7 import 'package:analyzer/dart/ast/token.dart';
8 8 import 'package:analyzer/src/dart/ast/token.dart';
9 import 'package:analyzer/src/generated/error.dart'; 9 import 'package:analyzer/src/generated/error.dart';
10 import 'package:analyzer/src/generated/java_engine.dart'; 10 import 'package:analyzer/src/generated/java_engine.dart';
11 import 'package:analyzer/src/generated/source.dart'; 11 import 'package:analyzer/src/generated/source.dart';
12 12
13 /** 13 export 'package:analyzer/dart/ast/token.dart';
14 * The opening half of a grouping pair of tokens. This is used for curly 14 export 'package:analyzer/src/dart/ast/token.dart' hide SimpleToken;
15 * brackets ('{'), parentheses ('('), and square brackets ('[').
16 */
17 class BeginToken extends Token {
18 /**
19 * The token that corresponds to this token.
20 */
21 Token endToken;
22
23 /**
24 * Initialize a newly created token to have the given [type] at the given
25 * [offset].
26 */
27 BeginToken(TokenType type, int offset) : super(type, offset) {
28 assert(type == TokenType.OPEN_CURLY_BRACKET ||
29 type == TokenType.OPEN_PAREN ||
30 type == TokenType.OPEN_SQUARE_BRACKET ||
31 type == TokenType.STRING_INTERPOLATION_EXPRESSION);
32 }
33
34 @override
35 Token copy() => new BeginToken(type, offset);
36 }
37
38 /**
39 * A begin token that is preceded by comments.
40 */
41 class BeginTokenWithComment extends BeginToken {
42 /**
43 * The first comment in the list of comments that precede this token.
44 */
45 CommentToken _precedingComment;
46
47 /**
48 * Initialize a newly created token to have the given [type] at the given
49 * [offset] and to be preceded by the comments reachable from the given
50 * [comment].
51 */
52 BeginTokenWithComment(TokenType type, int offset, this._precedingComment)
53 : super(type, offset) {
54 _setCommentParent(_precedingComment);
55 }
56
57 CommentToken get precedingComments => _precedingComment;
58
59 void set precedingComments(CommentToken comment) {
60 _precedingComment = comment;
61 _setCommentParent(_precedingComment);
62 }
63
64 @override
65 void applyDelta(int delta) {
66 super.applyDelta(delta);
67 Token token = precedingComments;
68 while (token != null) {
69 token.applyDelta(delta);
70 token = token.next;
71 }
72 }
73
74 @override
75 Token copy() =>
76 new BeginTokenWithComment(type, offset, copyComments(precedingComments));
77 }
78 15
79 /** 16 /**
80 * A [CharacterReader] that reads a range of characters from another character 17 * A [CharacterReader] that reads a range of characters from another character
81 * reader. 18 * reader.
82 */ 19 */
83 class CharacterRangeReader extends CharacterReader { 20 class CharacterRangeReader extends CharacterReader {
84 /** 21 /**
85 * The reader from which the characters are actually being read. 22 * The reader from which the characters are actually being read.
86 */ 23 */
87 final CharacterReader baseReader; 24 final CharacterReader baseReader;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 @override 157 @override
221 int peek() { 158 int peek() {
222 if (_charOffset + 1 >= _stringLength) { 159 if (_charOffset + 1 >= _stringLength) {
223 return -1; 160 return -1;
224 } 161 }
225 return _sequence.codeUnitAt(_charOffset + 1); 162 return _sequence.codeUnitAt(_charOffset + 1);
226 } 163 }
227 } 164 }
228 165
229 /** 166 /**
230 * A token representing a comment.
231 */
232 class CommentToken extends StringToken {
233 /**
234 * The [Token] that contains this comment.
235 */
236 Token parent;
237
238 /**
239 * Initialize a newly created token to represent a token of the given [type]
240 * with the given [value] at the given [offset].
241 */
242 CommentToken(TokenType type, String value, int offset)
243 : super(type, value, offset);
244
245 @override
246 CommentToken copy() => new CommentToken(type, _value, offset);
247 }
248
249 /**
250 * A documentation comment token.
251 */
252 class DocumentationCommentToken extends CommentToken {
253 /**
254 * The references embedded within the documentation comment.
255 * This list will be empty unless this is a documentation comment that has
256 * references embedded within it.
257 */
258 final List<Token> references = <Token>[];
259
260 /**
261 * Initialize a newly created token to represent a token of the given [type]
262 * with the given [value] at the given [offset].
263 */
264 DocumentationCommentToken(TokenType type, String value, int offset)
265 : super(type, value, offset);
266
267 @override
268 CommentToken copy() {
269 DocumentationCommentToken copy =
270 new DocumentationCommentToken(type, _value, offset);
271 references.forEach((ref) => copy.references.add(ref.copy()));
272 return copy;
273 }
274 }
275
276 /**
277 * The keywords in the Dart programming language.
278 */
279 class Keyword {
280 static const Keyword ASSERT = const Keyword('ASSERT', "assert");
281
282 static const Keyword BREAK = const Keyword('BREAK', "break");
283
284 static const Keyword CASE = const Keyword('CASE', "case");
285
286 static const Keyword CATCH = const Keyword('CATCH', "catch");
287
288 static const Keyword CLASS = const Keyword('CLASS', "class");
289
290 static const Keyword CONST = const Keyword('CONST', "const");
291
292 static const Keyword CONTINUE = const Keyword('CONTINUE', "continue");
293
294 static const Keyword DEFAULT = const Keyword('DEFAULT', "default");
295
296 static const Keyword DO = const Keyword('DO', "do");
297
298 static const Keyword ELSE = const Keyword('ELSE', "else");
299
300 static const Keyword ENUM = const Keyword('ENUM', "enum");
301
302 static const Keyword EXTENDS = const Keyword('EXTENDS', "extends");
303
304 static const Keyword FALSE = const Keyword('FALSE', "false");
305
306 static const Keyword FINAL = const Keyword('FINAL', "final");
307
308 static const Keyword FINALLY = const Keyword('FINALLY', "finally");
309
310 static const Keyword FOR = const Keyword('FOR', "for");
311
312 static const Keyword IF = const Keyword('IF', "if");
313
314 static const Keyword IN = const Keyword('IN', "in");
315
316 static const Keyword IS = const Keyword('IS', "is");
317
318 static const Keyword NEW = const Keyword('NEW', "new");
319
320 static const Keyword NULL = const Keyword('NULL', "null");
321
322 static const Keyword RETHROW = const Keyword('RETHROW', "rethrow");
323
324 static const Keyword RETURN = const Keyword('RETURN', "return");
325
326 static const Keyword SUPER = const Keyword('SUPER', "super");
327
328 static const Keyword SWITCH = const Keyword('SWITCH', "switch");
329
330 static const Keyword THIS = const Keyword('THIS', "this");
331
332 static const Keyword THROW = const Keyword('THROW', "throw");
333
334 static const Keyword TRUE = const Keyword('TRUE', "true");
335
336 static const Keyword TRY = const Keyword('TRY', "try");
337
338 static const Keyword VAR = const Keyword('VAR', "var");
339
340 static const Keyword VOID = const Keyword('VOID', "void");
341
342 static const Keyword WHILE = const Keyword('WHILE', "while");
343
344 static const Keyword WITH = const Keyword('WITH', "with");
345
346 static const Keyword ABSTRACT = const Keyword('ABSTRACT', "abstract", true);
347
348 static const Keyword AS = const Keyword('AS', "as", true);
349
350 static const Keyword DEFERRED = const Keyword('DEFERRED', "deferred", true);
351
352 static const Keyword DYNAMIC = const Keyword('DYNAMIC', "dynamic", true);
353
354 static const Keyword EXPORT = const Keyword('EXPORT', "export", true);
355
356 static const Keyword EXTERNAL = const Keyword('EXTERNAL', "external", true);
357
358 static const Keyword FACTORY = const Keyword('FACTORY', "factory", true);
359
360 static const Keyword GET = const Keyword('GET', "get", true);
361
362 static const Keyword IMPLEMENTS =
363 const Keyword('IMPLEMENTS', "implements", true);
364
365 static const Keyword IMPORT = const Keyword('IMPORT', "import", true);
366
367 static const Keyword LIBRARY = const Keyword('LIBRARY', "library", true);
368
369 static const Keyword OPERATOR = const Keyword('OPERATOR', "operator", true);
370
371 static const Keyword PART = const Keyword('PART', "part", true);
372
373 static const Keyword SET = const Keyword('SET', "set", true);
374
375 static const Keyword STATIC = const Keyword('STATIC', "static", true);
376
377 static const Keyword TYPEDEF = const Keyword('TYPEDEF', "typedef", true);
378
379 static const List<Keyword> values = const [
380 ASSERT,
381 BREAK,
382 CASE,
383 CATCH,
384 CLASS,
385 CONST,
386 CONTINUE,
387 DEFAULT,
388 DO,
389 ELSE,
390 ENUM,
391 EXTENDS,
392 FALSE,
393 FINAL,
394 FINALLY,
395 FOR,
396 IF,
397 IN,
398 IS,
399 NEW,
400 NULL,
401 RETHROW,
402 RETURN,
403 SUPER,
404 SWITCH,
405 THIS,
406 THROW,
407 TRUE,
408 TRY,
409 VAR,
410 VOID,
411 WHILE,
412 WITH,
413 ABSTRACT,
414 AS,
415 DEFERRED,
416 DYNAMIC,
417 EXPORT,
418 EXTERNAL,
419 FACTORY,
420 GET,
421 IMPLEMENTS,
422 IMPORT,
423 LIBRARY,
424 OPERATOR,
425 PART,
426 SET,
427 STATIC,
428 TYPEDEF
429 ];
430
431 /**
432 * A table mapping the lexemes of keywords to the corresponding keyword.
433 */
434 static final Map<String, Keyword> keywords = _createKeywordMap();
435
436 /**
437 * The name of the keyword type.
438 */
439 final String name;
440
441 /**
442 * The lexeme for the keyword.
443 */
444 final String syntax;
445
446 /**
447 * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords
448 * can be used as identifiers.
449 */
450 final bool isPseudoKeyword;
451
452 /**
453 * Initialize a newly created keyword to have the given [name] and [syntax].
454 * The keyword is a pseudo-keyword if the [isPseudoKeyword] flag is `true`.
455 */
456 const Keyword(this.name, this.syntax, [this.isPseudoKeyword = false]);
457
458 @override
459 String toString() => name;
460
461 /**
462 * Create a table mapping the lexemes of keywords to the corresponding keyword
463 * and return the table that was created.
464 */
465 static Map<String, Keyword> _createKeywordMap() {
466 LinkedHashMap<String, Keyword> result =
467 new LinkedHashMap<String, Keyword>();
468 for (Keyword keyword in values) {
469 result[keyword.syntax] = keyword;
470 }
471 return result;
472 }
473 }
474
475 /**
476 * A state in a state machine used to scan keywords. 167 * A state in a state machine used to scan keywords.
477 */ 168 */
478 class KeywordState { 169 class KeywordState {
479 /** 170 /**
480 * An empty transition table used by leaf states. 171 * An empty transition table used by leaf states.
481 */ 172 */
482 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26); 173 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
483 174
484 /** 175 /**
485 * The initial state in the state machine. 176 * The initial state in the state machine.
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 List<String> strings = new List<String>(values.length); 263 List<String> strings = new List<String>(values.length);
573 for (int i = 0; i < values.length; i++) { 264 for (int i = 0; i < values.length; i++) {
574 strings[i] = values[i].syntax; 265 strings[i] = values[i].syntax;
575 } 266 }
576 strings.sort(); 267 strings.sort();
577 return _computeKeywordStateTable(0, strings, 0, strings.length); 268 return _computeKeywordStateTable(0, strings, 0, strings.length);
578 } 269 }
579 } 270 }
580 271
581 /** 272 /**
582 * A token representing a keyword in the language.
583 */
584 class KeywordToken extends Token {
585 /**
586 * The keyword being represented by this token.
587 */
588 final Keyword keyword;
589
590 /**
591 * Initialize a newly created token to represent the given [keyword] at the
592 * given [offset].
593 */
594 KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset);
595
596 @override
597 String get lexeme => keyword.syntax;
598
599 @override
600 Token copy() => new KeywordToken(keyword, offset);
601
602 @override
603 Keyword value() => keyword;
604 }
605
606 /**
607 * A keyword token that is preceded by comments.
608 */
609 class KeywordTokenWithComment extends KeywordToken {
610 /**
611 * The first comment in the list of comments that precede this token.
612 */
613 CommentToken _precedingComment;
614
615 /**
616 * Initialize a newly created token to to represent the given [keyword] at the
617 * given [offset] and to be preceded by the comments reachable from the given
618 * [comment].
619 */
620 KeywordTokenWithComment(Keyword keyword, int offset, this._precedingComment)
621 : super(keyword, offset) {
622 _setCommentParent(_precedingComment);
623 }
624
625 CommentToken get precedingComments => _precedingComment;
626
627 void set precedingComments(CommentToken comment) {
628 _precedingComment = comment;
629 _setCommentParent(_precedingComment);
630 }
631
632 @override
633 void applyDelta(int delta) {
634 super.applyDelta(delta);
635 Token token = precedingComments;
636 while (token != null) {
637 token.applyDelta(delta);
638 token = token.next;
639 }
640 }
641
642 @override
643 Token copy() => new KeywordTokenWithComment(
644 keyword, offset, copyComments(precedingComments));
645 }
646
647 /**
648 * The class `Scanner` implements a scanner for Dart code. 273 * The class `Scanner` implements a scanner for Dart code.
649 * 274 *
650 * The lexical structure of Dart is ambiguous without knowledge of the context 275 * The lexical structure of Dart is ambiguous without knowledge of the context
651 * in which a token is being scanned. For example, without context we cannot 276 * in which a token is being scanned. For example, without context we cannot
652 * determine whether source of the form "<<" should be scanned as a single 277 * determine whether source of the form "<<" should be scanned as a single
653 * left-shift operator or as two left angle brackets. This scanner does not have 278 * left-shift operator or as two left angle brackets. This scanner does not have
654 * any context, so it always resolves such conflicts by scanning the longest 279 * any context, so it always resolves such conflicts by scanning the longest
655 * possible token. 280 * possible token.
656 */ 281 */
657 class Scanner { 282 class Scanner {
(...skipping 1237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1895 : super(name, message, correction); 1520 : super(name, message, correction);
1896 1521
1897 @override 1522 @override
1898 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; 1523 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
1899 1524
1900 @override 1525 @override
1901 ErrorType get type => ErrorType.SYNTACTIC_ERROR; 1526 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
1902 } 1527 }
1903 1528
1904 /** 1529 /**
1905 * A token whose value is independent of it's type.
1906 */
1907 class StringToken extends Token {
1908 /**
1909 * The lexeme represented by this token.
1910 */
1911 String _value;
1912
1913 /**
1914 * Initialize a newly created token to represent a token of the given [type]
1915 * with the given [value] at the given [offset].
1916 */
1917 StringToken(TokenType type, String value, int offset) : super(type, offset) {
1918 this._value = StringUtilities.intern(value);
1919 }
1920
1921 @override
1922 String get lexeme => _value;
1923
1924 @override
1925 Token copy() => new StringToken(type, _value, offset);
1926
1927 @override
1928 String value() => _value;
1929 }
1930
1931 /**
1932 * A string token that is preceded by comments.
1933 */
1934 class StringTokenWithComment extends StringToken {
1935 /**
1936 * The first comment in the list of comments that precede this token.
1937 */
1938 CommentToken _precedingComment;
1939
1940 /**
1941 * Initialize a newly created token to have the given [type] at the given
1942 * [offset] and to be preceded by the comments reachable from the given
1943 * [comment].
1944 */
1945 StringTokenWithComment(
1946 TokenType type, String value, int offset, this._precedingComment)
1947 : super(type, value, offset) {
1948 _setCommentParent(_precedingComment);
1949 }
1950
1951 CommentToken get precedingComments => _precedingComment;
1952
1953 void set precedingComments(CommentToken comment) {
1954 _precedingComment = comment;
1955 _setCommentParent(_precedingComment);
1956 }
1957
1958 @override
1959 void applyDelta(int delta) {
1960 super.applyDelta(delta);
1961 Token token = precedingComments;
1962 while (token != null) {
1963 token.applyDelta(delta);
1964 token = token.next;
1965 }
1966 }
1967
1968 @override
1969 Token copy() => new StringTokenWithComment(
1970 type, lexeme, offset, copyComments(precedingComments));
1971 }
1972
1973 /**
1974 * A [CharacterReader] that reads characters from a character sequence, but adds 1530 * A [CharacterReader] that reads characters from a character sequence, but adds
1975 * a delta when reporting the current character offset so that the character 1531 * a delta when reporting the current character offset so that the character
1976 * sequence can be a subsequence from a larger sequence. 1532 * sequence can be a subsequence from a larger sequence.
1977 */ 1533 */
1978 class SubSequenceReader extends CharSequenceReader { 1534 class SubSequenceReader extends CharSequenceReader {
1979 /** 1535 /**
1980 * The offset from the beginning of the file to the beginning of the source 1536 * The offset from the beginning of the file to the beginning of the source
1981 * being scanned. 1537 * being scanned.
1982 */ 1538 */
1983 final int _offsetDelta; 1539 final int _offsetDelta;
(...skipping 10 matching lines...) Expand all
1994 1550
1995 @override 1551 @override
1996 void set offset(int offset) { 1552 void set offset(int offset) {
1997 super.offset = offset - _offsetDelta; 1553 super.offset = offset - _offsetDelta;
1998 } 1554 }
1999 1555
2000 @override 1556 @override
2001 String getString(int start, int endDelta) => 1557 String getString(int start, int endDelta) =>
2002 super.getString(start - _offsetDelta, endDelta); 1558 super.getString(start - _offsetDelta, endDelta);
2003 } 1559 }
2004
2005 /**
2006 * A token whose value is independent of it's type.
2007 */
2008 class SyntheticStringToken extends StringToken {
2009 /**
2010 * Initialize a newly created token to represent a token of the given [type]
2011 * with the given [value] at the given [offset].
2012 */
2013 SyntheticStringToken(TokenType type, String value, int offset)
2014 : super(type, value, offset);
2015
2016 @override
2017 bool get isSynthetic => true;
2018 }
2019
2020 /**
2021 * A token that was scanned from the input. Each token knows which tokens
2022 * precede and follow it, acting as a link in a doubly linked list of tokens.
2023 */
2024 class Token {
2025 /**
2026 * The type of the token.
2027 */
2028 final TokenType type;
2029
2030 /**
2031 * The offset from the beginning of the file to the first character in the
2032 * token.
2033 */
2034 int offset = 0;
2035
2036 /**
2037 * The previous token in the token stream.
2038 */
2039 Token previous;
2040
2041 /**
2042 * The next token in the token stream.
2043 */
2044 Token _next;
2045
2046 /**
2047 * Initialize a newly created token to have the given [type] and [offset].
2048 */
2049 Token(this.type, this.offset);
2050
2051 /**
2052 * Return the offset from the beginning of the file to the character after the
2053 * last character of the token.
2054 */
2055 int get end => offset + length;
2056
2057 /**
2058 * Return `true` if this token represents an operator.
2059 */
2060 bool get isOperator => type.isOperator;
2061
2062 /**
2063 * Return `true` if this token is a synthetic token. A synthetic token is a
2064 * token that was introduced by the parser in order to recover from an error
2065 * in the code.
2066 */
2067 bool get isSynthetic => length == 0;
2068
2069 /**
2070 * Return `true` if this token represents an operator that can be defined by
2071 * users.
2072 */
2073 bool get isUserDefinableOperator => type.isUserDefinableOperator;
2074
2075 /**
2076 * Return the number of characters in the node's source range.
2077 */
2078 int get length => lexeme.length;
2079
2080 /**
2081 * Return the lexeme that represents this token.
2082 */
2083 String get lexeme => type.lexeme;
2084
2085 /**
2086 * Return the next token in the token stream.
2087 */
2088 Token get next => _next;
2089
2090 /**
2091 * Return the first comment in the list of comments that precede this token,
2092 * or `null` if there are no comments preceding this token. Additional
2093 * comments can be reached by following the token stream using [next] until
2094 * `null` is returned.
2095 *
2096 * For example, if the original contents were `/* one */ /* two */ id`, then
2097 * the first preceding comment token will have a lexeme of `/* one */` and
2098 * the next comment token will have a lexeme of `/* two */`.
2099 */
2100 CommentToken get precedingComments => null;
2101
2102 /**
2103 * Apply (add) the given [delta] to this token's offset.
2104 */
2105 void applyDelta(int delta) {
2106 offset += delta;
2107 }
2108
2109 /**
2110 * Return a newly created token that is a copy of this token but that is not a
2111 * part of any token stream.
2112 */
2113 Token copy() => new Token(type, offset);
2114
2115 /**
2116 * Copy a linked list of comment tokens identical to the given comment tokens.
2117 */
2118 Token copyComments(Token token) {
2119 if (token == null) {
2120 return null;
2121 }
2122 Token head = token.copy();
2123 Token tail = head;
2124 token = token.next;
2125 while (token != null) {
2126 tail = tail.setNext(token.copy());
2127 token = token.next;
2128 }
2129 return head;
2130 }
2131
2132 /**
2133 * Return `true` if this token has any one of the given [types].
2134 */
2135 bool matchesAny(List<TokenType> types) {
2136 for (TokenType type in types) {
2137 if (this.type == type) {
2138 return true;
2139 }
2140 }
2141 return false;
2142 }
2143
2144 /**
2145 * Set the next token in the token stream to the given [token]. This has the
2146 * side-effect of setting this token to be the previous token for the given
2147 * token. Return the token that was passed in.
2148 */
2149 Token setNext(Token token) {
2150 _next = token;
2151 token.previous = this;
2152 return token;
2153 }
2154
2155 /**
2156 * Set the next token in the token stream to the given token without changing
2157 * which token is the previous token for the given token. Return the token
2158 * that was passed in.
2159 */
2160 Token setNextWithoutSettingPrevious(Token token) {
2161 _next = token;
2162 return token;
2163 }
2164
2165 @override
2166 String toString() => lexeme;
2167
2168 /**
2169 * Return the value of this token. For keyword tokens, this is the keyword
2170 * associated with the token, for other tokens it is the lexeme associated
2171 * with the token.
2172 */
2173 Object value() => type.lexeme;
2174
2175 /**
2176 * Sets the `parent` property to `this` for the given [comment] and all the
2177 * next tokens.
2178 */
2179 void _setCommentParent(CommentToken comment) {
2180 while (comment != null) {
2181 comment.parent = this;
2182 comment = comment.next;
2183 }
2184 }
2185
2186 /**
2187 * Compare the given [tokens] to find the token that appears first in the
2188 * source being parsed. That is, return the left-most of all of the tokens.
2189 * The list must be non-`null`, but the elements of the list are allowed to be
2190 * `null`. Return the token with the smallest offset, or `null` if the list is
2191 * empty or if all of the elements of the list are `null`.
2192 */
2193 static Token lexicallyFirst(List<Token> tokens) {
2194 Token first = null;
2195 int offset = -1;
2196 for (Token token in tokens) {
2197 if (token != null && (offset < 0 || token.offset < offset)) {
2198 first = token;
2199 offset = token.offset;
2200 }
2201 }
2202 return first;
2203 }
2204 }
2205
2206 /**
2207 * The classes (or groups) of tokens with a similar use.
2208 */
2209 class TokenClass {
2210 /**
2211 * A value used to indicate that the token type is not part of any specific
2212 * class of token.
2213 */
2214 static const TokenClass NO_CLASS = const TokenClass('NO_CLASS');
2215
2216 /**
2217 * A value used to indicate that the token type is an additive operator.
2218 */
2219 static const TokenClass ADDITIVE_OPERATOR =
2220 const TokenClass('ADDITIVE_OPERATOR', 13);
2221
2222 /**
2223 * A value used to indicate that the token type is an assignment operator.
2224 */
2225 static const TokenClass ASSIGNMENT_OPERATOR =
2226 const TokenClass('ASSIGNMENT_OPERATOR', 1);
2227
2228 /**
2229 * A value used to indicate that the token type is a bitwise-and operator.
2230 */
2231 static const TokenClass BITWISE_AND_OPERATOR =
2232 const TokenClass('BITWISE_AND_OPERATOR', 11);
2233
2234 /**
2235 * A value used to indicate that the token type is a bitwise-or operator.
2236 */
2237 static const TokenClass BITWISE_OR_OPERATOR =
2238 const TokenClass('BITWISE_OR_OPERATOR', 9);
2239
2240 /**
2241 * A value used to indicate that the token type is a bitwise-xor operator.
2242 */
2243 static const TokenClass BITWISE_XOR_OPERATOR =
2244 const TokenClass('BITWISE_XOR_OPERATOR', 10);
2245
2246 /**
2247 * A value used to indicate that the token type is a cascade operator.
2248 */
2249 static const TokenClass CASCADE_OPERATOR =
2250 const TokenClass('CASCADE_OPERATOR', 2);
2251
2252 /**
2253 * A value used to indicate that the token type is a conditional operator.
2254 */
2255 static const TokenClass CONDITIONAL_OPERATOR =
2256 const TokenClass('CONDITIONAL_OPERATOR', 3);
2257
2258 /**
2259 * A value used to indicate that the token type is an equality operator.
2260 */
2261 static const TokenClass EQUALITY_OPERATOR =
2262 const TokenClass('EQUALITY_OPERATOR', 7);
2263
2264 /**
2265 * A value used to indicate that the token type is an if-null operator.
2266 */
2267 static const TokenClass IF_NULL_OPERATOR =
2268 const TokenClass('IF_NULL_OPERATOR', 4);
2269
2270 /**
2271 * A value used to indicate that the token type is a logical-and operator.
2272 */
2273 static const TokenClass LOGICAL_AND_OPERATOR =
2274 const TokenClass('LOGICAL_AND_OPERATOR', 6);
2275
2276 /**
2277 * A value used to indicate that the token type is a logical-or operator.
2278 */
2279 static const TokenClass LOGICAL_OR_OPERATOR =
2280 const TokenClass('LOGICAL_OR_OPERATOR', 5);
2281
2282 /**
2283 * A value used to indicate that the token type is a multiplicative operator.
2284 */
2285 static const TokenClass MULTIPLICATIVE_OPERATOR =
2286 const TokenClass('MULTIPLICATIVE_OPERATOR', 14);
2287
2288 /**
2289 * A value used to indicate that the token type is a relational operator.
2290 */
2291 static const TokenClass RELATIONAL_OPERATOR =
2292 const TokenClass('RELATIONAL_OPERATOR', 8);
2293
2294 /**
2295 * A value used to indicate that the token type is a shift operator.
2296 */
2297 static const TokenClass SHIFT_OPERATOR =
2298 const TokenClass('SHIFT_OPERATOR', 12);
2299
2300 /**
2301 * A value used to indicate that the token type is a unary operator.
2302 */
2303 static const TokenClass UNARY_POSTFIX_OPERATOR =
2304 const TokenClass('UNARY_POSTFIX_OPERATOR', 16);
2305
2306 /**
2307 * A value used to indicate that the token type is a unary operator.
2308 */
2309 static const TokenClass UNARY_PREFIX_OPERATOR =
2310 const TokenClass('UNARY_PREFIX_OPERATOR', 15);
2311
2312 /**
2313 * The name of the token class.
2314 */
2315 final String name;
2316
2317 /**
2318 * The precedence of tokens of this class, or `0` if the such tokens do not
2319 * represent an operator.
2320 */
2321 final int precedence;
2322
2323 const TokenClass(this.name, [this.precedence = 0]);
2324
2325 @override
2326 String toString() => name;
2327 }
2328
2329 /**
2330 * The types of tokens that can be returned by the scanner.
2331 */
2332 class TokenType {
2333 /**
2334 * The type of the token that marks the end of the input.
2335 */
2336 static const TokenType EOF = const TokenType_EOF('EOF');
2337
2338 static const TokenType DOUBLE = const TokenType('DOUBLE');
2339
2340 static const TokenType HEXADECIMAL = const TokenType('HEXADECIMAL');
2341
2342 static const TokenType IDENTIFIER = const TokenType('IDENTIFIER');
2343
2344 static const TokenType INT = const TokenType('INT');
2345
2346 static const TokenType KEYWORD = const TokenType('KEYWORD');
2347
2348 static const TokenType MULTI_LINE_COMMENT =
2349 const TokenType('MULTI_LINE_COMMENT');
2350
2351 static const TokenType SCRIPT_TAG = const TokenType('SCRIPT_TAG');
2352
2353 static const TokenType SINGLE_LINE_COMMENT =
2354 const TokenType('SINGLE_LINE_COMMENT');
2355
2356 static const TokenType STRING = const TokenType('STRING');
2357
2358 static const TokenType AMPERSAND =
2359 const TokenType('AMPERSAND', TokenClass.BITWISE_AND_OPERATOR, "&");
2360
2361 static const TokenType AMPERSAND_AMPERSAND = const TokenType(
2362 'AMPERSAND_AMPERSAND', TokenClass.LOGICAL_AND_OPERATOR, "&&");
2363
2364 static const TokenType AMPERSAND_EQ =
2365 const TokenType('AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, "&=");
2366
2367 static const TokenType AT = const TokenType('AT', TokenClass.NO_CLASS, "@");
2368
2369 static const TokenType BANG =
2370 const TokenType('BANG', TokenClass.UNARY_PREFIX_OPERATOR, "!");
2371
2372 static const TokenType BANG_EQ =
2373 const TokenType('BANG_EQ', TokenClass.EQUALITY_OPERATOR, "!=");
2374
2375 static const TokenType BAR =
2376 const TokenType('BAR', TokenClass.BITWISE_OR_OPERATOR, "|");
2377
2378 static const TokenType BAR_BAR =
2379 const TokenType('BAR_BAR', TokenClass.LOGICAL_OR_OPERATOR, "||");
2380
2381 static const TokenType BAR_EQ =
2382 const TokenType('BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "|=");
2383
2384 static const TokenType COLON =
2385 const TokenType('COLON', TokenClass.NO_CLASS, ":");
2386
2387 static const TokenType COMMA =
2388 const TokenType('COMMA', TokenClass.NO_CLASS, ",");
2389
2390 static const TokenType CARET =
2391 const TokenType('CARET', TokenClass.BITWISE_XOR_OPERATOR, "^");
2392
2393 static const TokenType CARET_EQ =
2394 const TokenType('CARET_EQ', TokenClass.ASSIGNMENT_OPERATOR, "^=");
2395
2396 static const TokenType CLOSE_CURLY_BRACKET =
2397 const TokenType('CLOSE_CURLY_BRACKET', TokenClass.NO_CLASS, "}");
2398
2399 static const TokenType CLOSE_PAREN =
2400 const TokenType('CLOSE_PAREN', TokenClass.NO_CLASS, ")");
2401
2402 static const TokenType CLOSE_SQUARE_BRACKET =
2403 const TokenType('CLOSE_SQUARE_BRACKET', TokenClass.NO_CLASS, "]");
2404
2405 static const TokenType EQ =
2406 const TokenType('EQ', TokenClass.ASSIGNMENT_OPERATOR, "=");
2407
2408 static const TokenType EQ_EQ =
2409 const TokenType('EQ_EQ', TokenClass.EQUALITY_OPERATOR, "==");
2410
2411 static const TokenType FUNCTION =
2412 const TokenType('FUNCTION', TokenClass.NO_CLASS, "=>");
2413
2414 static const TokenType GT =
2415 const TokenType('GT', TokenClass.RELATIONAL_OPERATOR, ">");
2416
2417 static const TokenType GT_EQ =
2418 const TokenType('GT_EQ', TokenClass.RELATIONAL_OPERATOR, ">=");
2419
2420 static const TokenType GT_GT =
2421 const TokenType('GT_GT', TokenClass.SHIFT_OPERATOR, ">>");
2422
2423 static const TokenType GT_GT_EQ =
2424 const TokenType('GT_GT_EQ', TokenClass.ASSIGNMENT_OPERATOR, ">>=");
2425
2426 static const TokenType HASH =
2427 const TokenType('HASH', TokenClass.NO_CLASS, "#");
2428
2429 static const TokenType INDEX =
2430 const TokenType('INDEX', TokenClass.UNARY_POSTFIX_OPERATOR, "[]");
2431
2432 static const TokenType INDEX_EQ =
2433 const TokenType('INDEX_EQ', TokenClass.UNARY_POSTFIX_OPERATOR, "[]=");
2434
2435 static const TokenType IS =
2436 const TokenType('IS', TokenClass.RELATIONAL_OPERATOR, "is");
2437
2438 static const TokenType LT =
2439 const TokenType('LT', TokenClass.RELATIONAL_OPERATOR, "<");
2440
2441 static const TokenType LT_EQ =
2442 const TokenType('LT_EQ', TokenClass.RELATIONAL_OPERATOR, "<=");
2443
2444 static const TokenType LT_LT =
2445 const TokenType('LT_LT', TokenClass.SHIFT_OPERATOR, "<<");
2446
2447 static const TokenType LT_LT_EQ =
2448 const TokenType('LT_LT_EQ', TokenClass.ASSIGNMENT_OPERATOR, "<<=");
2449
2450 static const TokenType MINUS =
2451 const TokenType('MINUS', TokenClass.ADDITIVE_OPERATOR, "-");
2452
2453 static const TokenType MINUS_EQ =
2454 const TokenType('MINUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, "-=");
2455
2456 static const TokenType MINUS_MINUS =
2457 const TokenType('MINUS_MINUS', TokenClass.UNARY_PREFIX_OPERATOR, "--");
2458
2459 static const TokenType OPEN_CURLY_BRACKET =
2460 const TokenType('OPEN_CURLY_BRACKET', TokenClass.NO_CLASS, "{");
2461
2462 static const TokenType OPEN_PAREN =
2463 const TokenType('OPEN_PAREN', TokenClass.UNARY_POSTFIX_OPERATOR, "(");
2464
2465 static const TokenType OPEN_SQUARE_BRACKET = const TokenType(
2466 'OPEN_SQUARE_BRACKET', TokenClass.UNARY_POSTFIX_OPERATOR, "[");
2467
2468 static const TokenType PERCENT =
2469 const TokenType('PERCENT', TokenClass.MULTIPLICATIVE_OPERATOR, "%");
2470
2471 static const TokenType PERCENT_EQ =
2472 const TokenType('PERCENT_EQ', TokenClass.ASSIGNMENT_OPERATOR, "%=");
2473
2474 static const TokenType PERIOD =
2475 const TokenType('PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, ".");
2476
2477 static const TokenType PERIOD_PERIOD =
2478 const TokenType('PERIOD_PERIOD', TokenClass.CASCADE_OPERATOR, "..");
2479
2480 static const TokenType PLUS =
2481 const TokenType('PLUS', TokenClass.ADDITIVE_OPERATOR, "+");
2482
2483 static const TokenType PLUS_EQ =
2484 const TokenType('PLUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, "+=");
2485
2486 static const TokenType PLUS_PLUS =
2487 const TokenType('PLUS_PLUS', TokenClass.UNARY_PREFIX_OPERATOR, "++");
2488
2489 static const TokenType QUESTION =
2490 const TokenType('QUESTION', TokenClass.CONDITIONAL_OPERATOR, "?");
2491
2492 static const TokenType QUESTION_PERIOD = const TokenType(
2493 'QUESTION_PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '?.');
2494
2495 static const TokenType QUESTION_QUESTION =
2496 const TokenType('QUESTION_QUESTION', TokenClass.IF_NULL_OPERATOR, '??');
2497
2498 static const TokenType QUESTION_QUESTION_EQ = const TokenType(
2499 'QUESTION_QUESTION_EQ', TokenClass.ASSIGNMENT_OPERATOR, '??=');
2500
2501 static const TokenType SEMICOLON =
2502 const TokenType('SEMICOLON', TokenClass.NO_CLASS, ";");
2503
2504 static const TokenType SLASH =
2505 const TokenType('SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, "/");
2506
2507 static const TokenType SLASH_EQ =
2508 const TokenType('SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, "/=");
2509
2510 static const TokenType STAR =
2511 const TokenType('STAR', TokenClass.MULTIPLICATIVE_OPERATOR, "*");
2512
2513 static const TokenType STAR_EQ =
2514 const TokenType('STAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "*=");
2515
2516 static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType(
2517 'STRING_INTERPOLATION_EXPRESSION', TokenClass.NO_CLASS, "\${");
2518
2519 static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType(
2520 'STRING_INTERPOLATION_IDENTIFIER', TokenClass.NO_CLASS, "\$");
2521
2522 static const TokenType TILDE =
2523 const TokenType('TILDE', TokenClass.UNARY_PREFIX_OPERATOR, "~");
2524
2525 static const TokenType TILDE_SLASH =
2526 const TokenType('TILDE_SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, "~/");
2527
2528 static const TokenType TILDE_SLASH_EQ =
2529 const TokenType('TILDE_SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, "~/=");
2530
2531 static const TokenType BACKPING =
2532 const TokenType('BACKPING', TokenClass.NO_CLASS, "`");
2533
2534 static const TokenType BACKSLASH =
2535 const TokenType('BACKSLASH', TokenClass.NO_CLASS, "\\");
2536
2537 static const TokenType PERIOD_PERIOD_PERIOD =
2538 const TokenType('PERIOD_PERIOD_PERIOD', TokenClass.NO_CLASS, "...");
2539
2540 static const TokenType GENERIC_METHOD_TYPE_LIST =
2541 const TokenType('GENERIC_METHOD_TYPE_LIST');
2542
2543 static const TokenType GENERIC_METHOD_TYPE_ASSIGN =
2544 const TokenType('GENERIC_METHOD_TYPE_ASSIGN');
2545
2546 /**
2547 * The class of the token.
2548 */
2549 final TokenClass _tokenClass;
2550
2551 /**
2552 * The name of the token type.
2553 */
2554 final String name;
2555
2556 /**
2557 * The lexeme that defines this type of token, or `null` if there is more than
2558 * one possible lexeme for this type of token.
2559 */
2560 final String lexeme;
2561
2562 const TokenType(this.name,
2563 [this._tokenClass = TokenClass.NO_CLASS, this.lexeme = null]);
2564
2565 /**
2566 * Return `true` if this type of token represents an additive operator.
2567 */
2568 bool get isAdditiveOperator => _tokenClass == TokenClass.ADDITIVE_OPERATOR;
2569
2570 /**
2571 * Return `true` if this type of token represents an assignment operator.
2572 */
2573 bool get isAssignmentOperator =>
2574 _tokenClass == TokenClass.ASSIGNMENT_OPERATOR;
2575
2576 /**
2577 * Return `true` if this type of token represents an associative operator. An
2578 * associative operator is an operator for which the following equality is
2579 * true: `(a * b) * c == a * (b * c)`. In other words, if the result of
2580 * applying the operator to multiple operands does not depend on the order in
2581 * which those applications occur.
2582 *
2583 * Note: This method considers the logical-and and logical-or operators to be
2584 * associative, even though the order in which the application of those
2585 * operators can have an effect because evaluation of the right-hand operand
2586 * is conditional.
2587 */
2588 bool get isAssociativeOperator =>
2589 this == AMPERSAND ||
2590 this == AMPERSAND_AMPERSAND ||
2591 this == BAR ||
2592 this == BAR_BAR ||
2593 this == CARET ||
2594 this == PLUS ||
2595 this == STAR;
2596
2597 /**
2598 * Return `true` if this type of token represents an equality operator.
2599 */
2600 bool get isEqualityOperator => _tokenClass == TokenClass.EQUALITY_OPERATOR;
2601
2602 /**
2603 * Return `true` if this type of token represents an increment operator.
2604 */
2605 bool get isIncrementOperator =>
2606 identical(lexeme, "++") || identical(lexeme, "--");
2607
2608 /**
2609 * Return `true` if this type of token represents a multiplicative operator.
2610 */
2611 bool get isMultiplicativeOperator =>
2612 _tokenClass == TokenClass.MULTIPLICATIVE_OPERATOR;
2613
2614 /**
2615 * Return `true` if this token type represents an operator.
2616 */
2617 bool get isOperator =>
2618 _tokenClass != TokenClass.NO_CLASS &&
2619 this != OPEN_PAREN &&
2620 this != OPEN_SQUARE_BRACKET &&
2621 this != PERIOD;
2622
2623 /**
2624 * Return `true` if this type of token represents a relational operator.
2625 */
2626 bool get isRelationalOperator =>
2627 _tokenClass == TokenClass.RELATIONAL_OPERATOR;
2628
2629 /**
2630 * Return `true` if this type of token represents a shift operator.
2631 */
2632 bool get isShiftOperator => _tokenClass == TokenClass.SHIFT_OPERATOR;
2633
2634 /**
2635 * Return `true` if this type of token represents a unary postfix operator.
2636 */
2637 bool get isUnaryPostfixOperator =>
2638 _tokenClass == TokenClass.UNARY_POSTFIX_OPERATOR;
2639
2640 /**
2641 * Return `true` if this type of token represents a unary prefix operator.
2642 */
2643 bool get isUnaryPrefixOperator =>
2644 _tokenClass == TokenClass.UNARY_PREFIX_OPERATOR;
2645
2646 /**
2647 * Return `true` if this token type represents an operator that can be defined
2648 * by users.
2649 */
2650 bool get isUserDefinableOperator =>
2651 identical(lexeme, "==") ||
2652 identical(lexeme, "~") ||
2653 identical(lexeme, "[]") ||
2654 identical(lexeme, "[]=") ||
2655 identical(lexeme, "*") ||
2656 identical(lexeme, "/") ||
2657 identical(lexeme, "%") ||
2658 identical(lexeme, "~/") ||
2659 identical(lexeme, "+") ||
2660 identical(lexeme, "-") ||
2661 identical(lexeme, "<<") ||
2662 identical(lexeme, ">>") ||
2663 identical(lexeme, ">=") ||
2664 identical(lexeme, ">") ||
2665 identical(lexeme, "<=") ||
2666 identical(lexeme, "<") ||
2667 identical(lexeme, "&") ||
2668 identical(lexeme, "^") ||
2669 identical(lexeme, "|");
2670
2671 /**
2672 * Return the precedence of the token, or `0` if the token does not represent
2673 * an operator.
2674 */
2675 int get precedence => _tokenClass.precedence;
2676
2677 @override
2678 String toString() => name;
2679 }
2680
2681 class TokenType_EOF extends TokenType {
2682 const TokenType_EOF(String name) : super(name, TokenClass.NO_CLASS, "");
2683
2684 @override
2685 String toString() => "-eof-";
2686 }
2687
2688 /**
2689 * A normal token that is preceded by comments.
2690 */
2691 class TokenWithComment extends Token {
2692 /**
2693 * The first comment in the list of comments that precede this token.
2694 */
2695 CommentToken _precedingComment;
2696
2697 /**
2698 * Initialize a newly created token to have the given [type] at the given
2699 * [offset] and to be preceded by the comments reachable from the given
2700 * [comment].
2701 */
2702 TokenWithComment(TokenType type, int offset, this._precedingComment)
2703 : super(type, offset) {
2704 _setCommentParent(_precedingComment);
2705 }
2706
2707 CommentToken get precedingComments => _precedingComment;
2708
2709 void set precedingComments(CommentToken comment) {
2710 _precedingComment = comment;
2711 _setCommentParent(_precedingComment);
2712 }
2713
2714 @override
2715 Token copy() => new TokenWithComment(type, offset, precedingComments);
2716 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/ast/token.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698