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

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

Issue 45573002: Rename analyzer_experimental to analyzer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweaks before publishing. Created 7 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // This code was auto-generated, is not intended to be edited, and is subject to
2 // significant change. Please see the README file for more information.
3 library engine.scanner;
4 import 'dart:collection';
5 import 'java_core.dart';
6 import 'java_engine.dart';
7 import 'source.dart';
8 import 'error.dart';
9 import 'instrumentation.dart';
10 import 'utilities_collection.dart' show TokenMap;
11 /**
12 * Instances of the abstract class `KeywordState` represent a state in a state m achine used to
13 * scan keywords.
14 *
15 * @coverage dart.engine.parser
16 */
17 class KeywordState {
18
19 /**
20 * An empty transition table used by leaf states.
21 */
22 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
23
24 /**
25 * The initial state in the state machine.
26 */
27 static KeywordState KEYWORD_STATE = createKeywordStateTable();
28
29 /**
30 * Create the next state in the state machine where we have already recognized the subset of
31 * strings in the given array of strings starting at the given offset and havi ng the given length.
32 * All of these strings have a common prefix and the next character is at the given start index.
33 *
34 * @param start the index of the character in the strings used to transition t o a new state
35 * @param strings an array containing all of the strings that will be recogniz ed by the state
36 * machine
37 * @param offset the offset of the first string in the array that has the pref ix that is assumed
38 * to have been recognized by the time we reach the state being built
39 * @param length the number of strings in the array that pass through the stat e being built
40 * @return the state that was created
41 */
42 static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length) {
43 List<KeywordState> result = new List<KeywordState>(26);
44 assert(length != 0);
45 int chunk = 0x0;
46 int chunkStart = -1;
47 bool isLeaf = false;
48 for (int i = offset; i < offset + length; i++) {
49 if (strings[i].length == start) {
50 isLeaf = true;
51 }
52 if (strings[i].length > start) {
53 int c = strings[i].codeUnitAt(start);
54 if (chunk != c) {
55 if (chunkStart != -1) {
56 result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, i - chunkStart);
57 }
58 chunkStart = i;
59 chunk = c;
60 }
61 }
62 }
63 if (chunkStart != -1) {
64 assert(result[chunk - 0x61] == null);
65 result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkS tart, offset + length - chunkStart);
66 } else {
67 assert(length == 1);
68 return new KeywordState(_EMPTY_TABLE, strings[offset]);
69 }
70 if (isLeaf) {
71 return new KeywordState(result, strings[offset]);
72 } else {
73 return new KeywordState(result, null);
74 }
75 }
76
77 /**
78 * Create the initial state in the state machine.
79 *
80 * @return the state that was created
81 */
82 static KeywordState createKeywordStateTable() {
83 List<Keyword> values = Keyword.values;
84 List<String> strings = new List<String>(values.length);
85 for (int i = 0; i < values.length; i++) {
86 strings[i] = values[i].syntax;
87 }
88 strings.sort();
89 return computeKeywordStateTable(0, strings, 0, strings.length);
90 }
91
92 /**
93 * A table mapping characters to the states to which those characters will tra nsition. (The index
94 * into the array is the offset from the character `'a'` to the transitioning character.)
95 */
96 List<KeywordState> _table;
97
98 /**
99 * The keyword that is recognized by this state, or `null` if this state is no t a terminal
100 * state.
101 */
102 Keyword _keyword2;
103
104 /**
105 * Initialize a newly created state to have the given transitions and to recog nize the keyword
106 * with the given syntax.
107 *
108 * @param table a table mapping characters to the states to which those charac ters will transition
109 * @param syntax the syntax of the keyword that is recognized by the state
110 */
111 KeywordState(List<KeywordState> table, String syntax) {
112 this._table = table;
113 this._keyword2 = (syntax == null) ? null : Keyword.keywords[syntax];
114 }
115
116 /**
117 * Return the keyword that was recognized by this state, or `null` if this sta te does not
118 * recognized a keyword.
119 *
120 * @return the keyword that was matched by reaching this state
121 */
122 Keyword keyword() => _keyword2;
123
124 /**
125 * Return the state that follows this state on a transition of the given chara cter, or
126 * `null` if there is no valid state reachable from this state with such a tra nsition.
127 *
128 * @param c the character used to transition from this state to another state
129 * @return the state that follows this state on a transition of the given char acter
130 */
131 KeywordState next(int c) => _table[c - 0x61];
132 }
133 /**
134 * The enumeration `ScannerErrorCode` defines the error codes used for errors de tected by the
135 * scanner.
136 *
137 * @coverage dart.engine.parser
138 */
139 class ScannerErrorCode extends Enum<ScannerErrorCode> implements ErrorCode {
140 static final ScannerErrorCode CHARACTER_EXPECTED_AFTER_SLASH = new ScannerErro rCode.con1('CHARACTER_EXPECTED_AFTER_SLASH', 0, "Character expected after slash" );
141 static final ScannerErrorCode ILLEGAL_CHARACTER = new ScannerErrorCode.con1('I LLEGAL_CHARACTER', 1, "Illegal character %x");
142 static final ScannerErrorCode MISSING_DIGIT = new ScannerErrorCode.con1('MISSI NG_DIGIT', 2, "Decimal digit expected");
143 static final ScannerErrorCode MISSING_HEX_DIGIT = new ScannerErrorCode.con1('M ISSING_HEX_DIGIT', 3, "Hexidecimal digit expected");
144 static final ScannerErrorCode MISSING_QUOTE = new ScannerErrorCode.con1('MISSI NG_QUOTE', 4, "Expected quote (' or \")");
145 static final ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT = new ScannerErr orCode.con1('UNTERMINATED_MULTI_LINE_COMMENT', 5, "Unterminated multi-line comme nt");
146 static final ScannerErrorCode UNTERMINATED_STRING_LITERAL = new ScannerErrorCo de.con1('UNTERMINATED_STRING_LITERAL', 6, "Unterminated string literal");
147 static final List<ScannerErrorCode> values = [
148 CHARACTER_EXPECTED_AFTER_SLASH,
149 ILLEGAL_CHARACTER,
150 MISSING_DIGIT,
151 MISSING_HEX_DIGIT,
152 MISSING_QUOTE,
153 UNTERMINATED_MULTI_LINE_COMMENT,
154 UNTERMINATED_STRING_LITERAL];
155
156 /**
157 * The template used to create the message to be displayed for this error.
158 */
159 String _message;
160
161 /**
162 * The template used to create the correction to be displayed for this error, or `null` if
163 * there is no correction information for this error.
164 */
165 String correction10;
166
167 /**
168 * Initialize a newly created error code to have the given message.
169 *
170 * @param message the message template used to create the message to be displa yed for this error
171 */
172 ScannerErrorCode.con1(String name, int ordinal, String message) : super(name, ordinal) {
173 this._message = message;
174 }
175
176 /**
177 * Initialize a newly created error code to have the given message and correct ion.
178 *
179 * @param message the template used to create the message to be displayed for the error
180 * @param correction the template used to create the correction to be displaye d for the error
181 */
182 ScannerErrorCode.con2(String name, int ordinal, String message, String correct ion) : super(name, ordinal) {
183 this._message = message;
184 this.correction10 = correction;
185 }
186 String get correction => correction10;
187 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
188 String get message => _message;
189 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
190 }
191 /**
192 * Instances of the class `SubSequenceReader` implement a [CharacterReader] that reads
193 * characters from a character sequence, but adds a delta when reporting the cur rent character
194 * offset so that the character sequence can be a subsequence from a larger sequ ence.
195 */
196 class SubSequenceReader extends CharSequenceReader {
197
198 /**
199 * The offset from the beginning of the file to the beginning of the source be ing scanned.
200 */
201 int _offsetDelta = 0;
202
203 /**
204 * Initialize a newly created reader to read the characters in the given seque nce.
205 *
206 * @param sequence the sequence from which characters will be read
207 * @param offsetDelta the offset from the beginning of the file to the beginni ng of the source
208 * being scanned
209 */
210 SubSequenceReader(CharSequence sequence, int offsetDelta) : super(sequence) {
211 this._offsetDelta = offsetDelta;
212 }
213 int get offset => _offsetDelta + super.offset;
214 String getString(int start, int endDelta) => super.getString(start - _offsetDe lta, endDelta);
215 void set offset(int offset) {
216 super.offset = offset - _offsetDelta;
217 }
218 }
219 /**
220 * Instances of the class `TokenWithComment` represent a string token that is pr eceded by
221 * comments.
222 *
223 * @coverage dart.engine.parser
224 */
225 class StringTokenWithComment extends StringToken {
226
227 /**
228 * The first comment in the list of comments that precede this token.
229 */
230 Token _precedingComment;
231
232 /**
233 * Initialize a newly created token to have the given type and offset and to b e preceded by the
234 * comments reachable from the given comment.
235 *
236 * @param type the type of the token
237 * @param offset the offset from the beginning of the file to the first charac ter in the token
238 * @param precedingComment the first comment in the list of comments that prec ede this token
239 */
240 StringTokenWithComment(TokenType type, String value, int offset, Token precedi ngComment) : super(type, value, offset) {
241 this._precedingComment = precedingComment;
242 }
243 Token copy() => new StringTokenWithComment(type, lexeme, offset, copyComments( _precedingComment));
244 Token get precedingComments => _precedingComment;
245 void applyDelta(int delta) {
246 super.applyDelta(delta);
247 Token token = _precedingComment;
248 while (token != null) {
249 token.applyDelta(delta);
250 token = token.next;
251 }
252 }
253 }
254 /**
255 * The enumeration `Keyword` defines the keywords in the Dart programming langua ge.
256 *
257 * @coverage dart.engine.parser
258 */
259 class Keyword extends Enum<Keyword> {
260 static final Keyword ASSERT = new Keyword.con1('ASSERT', 0, "assert");
261 static final Keyword BREAK = new Keyword.con1('BREAK', 1, "break");
262 static final Keyword CASE = new Keyword.con1('CASE', 2, "case");
263 static final Keyword CATCH = new Keyword.con1('CATCH', 3, "catch");
264 static final Keyword CLASS = new Keyword.con1('CLASS', 4, "class");
265 static final Keyword CONST = new Keyword.con1('CONST', 5, "const");
266 static final Keyword CONTINUE = new Keyword.con1('CONTINUE', 6, "continue");
267 static final Keyword DEFAULT = new Keyword.con1('DEFAULT', 7, "default");
268 static final Keyword DO = new Keyword.con1('DO', 8, "do");
269 static final Keyword ELSE = new Keyword.con1('ELSE', 9, "else");
270 static final Keyword ENUM = new Keyword.con1('ENUM', 10, "enum");
271 static final Keyword EXTENDS = new Keyword.con1('EXTENDS', 11, "extends");
272 static final Keyword FALSE = new Keyword.con1('FALSE', 12, "false");
273 static final Keyword FINAL = new Keyword.con1('FINAL', 13, "final");
274 static final Keyword FINALLY = new Keyword.con1('FINALLY', 14, "finally");
275 static final Keyword FOR = new Keyword.con1('FOR', 15, "for");
276 static final Keyword IF = new Keyword.con1('IF', 16, "if");
277 static final Keyword IN = new Keyword.con1('IN', 17, "in");
278 static final Keyword IS = new Keyword.con1('IS', 18, "is");
279 static final Keyword NEW = new Keyword.con1('NEW', 19, "new");
280 static final Keyword NULL = new Keyword.con1('NULL', 20, "null");
281 static final Keyword RETHROW = new Keyword.con1('RETHROW', 21, "rethrow");
282 static final Keyword RETURN = new Keyword.con1('RETURN', 22, "return");
283 static final Keyword SUPER = new Keyword.con1('SUPER', 23, "super");
284 static final Keyword SWITCH = new Keyword.con1('SWITCH', 24, "switch");
285 static final Keyword THIS = new Keyword.con1('THIS', 25, "this");
286 static final Keyword THROW = new Keyword.con1('THROW', 26, "throw");
287 static final Keyword TRUE = new Keyword.con1('TRUE', 27, "true");
288 static final Keyword TRY = new Keyword.con1('TRY', 28, "try");
289 static final Keyword VAR = new Keyword.con1('VAR', 29, "var");
290 static final Keyword VOID = new Keyword.con1('VOID', 30, "void");
291 static final Keyword WHILE = new Keyword.con1('WHILE', 31, "while");
292 static final Keyword WITH = new Keyword.con1('WITH', 32, "with");
293 static final Keyword ABSTRACT = new Keyword.con2('ABSTRACT', 33, "abstract", t rue);
294 static final Keyword AS = new Keyword.con2('AS', 34, "as", true);
295 static final Keyword DYNAMIC = new Keyword.con2('DYNAMIC', 35, "dynamic", true );
296 static final Keyword EXPORT = new Keyword.con2('EXPORT', 36, "export", true);
297 static final Keyword EXTERNAL = new Keyword.con2('EXTERNAL', 37, "external", t rue);
298 static final Keyword FACTORY = new Keyword.con2('FACTORY', 38, "factory", true );
299 static final Keyword GET = new Keyword.con2('GET', 39, "get", true);
300 static final Keyword IMPLEMENTS = new Keyword.con2('IMPLEMENTS', 40, "implemen ts", true);
301 static final Keyword IMPORT = new Keyword.con2('IMPORT', 41, "import", true);
302 static final Keyword LIBRARY = new Keyword.con2('LIBRARY', 42, "library", true );
303 static final Keyword OPERATOR = new Keyword.con2('OPERATOR', 43, "operator", t rue);
304 static final Keyword PART = new Keyword.con2('PART', 44, "part", true);
305 static final Keyword SET = new Keyword.con2('SET', 45, "set", true);
306 static final Keyword STATIC = new Keyword.con2('STATIC', 46, "static", true);
307 static final Keyword TYPEDEF = new Keyword.con2('TYPEDEF', 47, "typedef", true );
308 static final List<Keyword> values = [
309 ASSERT,
310 BREAK,
311 CASE,
312 CATCH,
313 CLASS,
314 CONST,
315 CONTINUE,
316 DEFAULT,
317 DO,
318 ELSE,
319 ENUM,
320 EXTENDS,
321 FALSE,
322 FINAL,
323 FINALLY,
324 FOR,
325 IF,
326 IN,
327 IS,
328 NEW,
329 NULL,
330 RETHROW,
331 RETURN,
332 SUPER,
333 SWITCH,
334 THIS,
335 THROW,
336 TRUE,
337 TRY,
338 VAR,
339 VOID,
340 WHILE,
341 WITH,
342 ABSTRACT,
343 AS,
344 DYNAMIC,
345 EXPORT,
346 EXTERNAL,
347 FACTORY,
348 GET,
349 IMPLEMENTS,
350 IMPORT,
351 LIBRARY,
352 OPERATOR,
353 PART,
354 SET,
355 STATIC,
356 TYPEDEF];
357
358 /**
359 * The lexeme for the keyword.
360 */
361 String syntax;
362
363 /**
364 * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords can be used as
365 * identifiers.
366 */
367 bool isPseudoKeyword = false;
368
369 /**
370 * A table mapping the lexemes of keywords to the corresponding keyword.
371 */
372 static Map<String, Keyword> keywords = createKeywordMap();
373
374 /**
375 * Create a table mapping the lexemes of keywords to the corresponding keyword .
376 *
377 * @return the table that was created
378 */
379 static Map<String, Keyword> createKeywordMap() {
380 LinkedHashMap<String, Keyword> result = new LinkedHashMap<String, Keyword>() ;
381 for (Keyword keyword in values) {
382 result[keyword.syntax] = keyword;
383 }
384 return result;
385 }
386
387 /**
388 * Initialize a newly created keyword to have the given syntax. The keyword is not a
389 * pseudo-keyword.
390 *
391 * @param syntax the lexeme for the keyword
392 */
393 Keyword.con1(String name, int ordinal, String syntax) : this.con2(name, ordina l, syntax, false);
394
395 /**
396 * Initialize a newly created keyword to have the given syntax. The keyword is a pseudo-keyword if
397 * the given flag is `true`.
398 *
399 * @param syntax the lexeme for the keyword
400 * @param isPseudoKeyword `true` if this keyword is a pseudo-keyword
401 */
402 Keyword.con2(String name, int ordinal, String syntax, bool isPseudoKeyword) : super(name, ordinal) {
403 this.syntax = syntax;
404 this.isPseudoKeyword = isPseudoKeyword;
405 }
406 }
407 /**
408 * Instances of the class `CharSequenceReader` implement a [CharacterReader] tha t reads
409 * characters from a character sequence.
410 */
411 class CharSequenceReader implements CharacterReader {
412
413 /**
414 * The sequence from which characters will be read.
415 */
416 CharSequence _sequence;
417
418 /**
419 * The number of characters in the string.
420 */
421 int _stringLength = 0;
422
423 /**
424 * The index, relative to the string, of the last character that was read.
425 */
426 int _charOffset = 0;
427
428 /**
429 * Initialize a newly created reader to read the characters in the given seque nce.
430 *
431 * @param sequence the sequence from which characters will be read
432 */
433 CharSequenceReader(CharSequence sequence) {
434 this._sequence = sequence;
435 this._stringLength = sequence.length();
436 this._charOffset = -1;
437 }
438 int advance() {
439 if (_charOffset + 1 >= _stringLength) {
440 return -1;
441 }
442 return _sequence.charAt(++_charOffset);
443 }
444 int get offset => _charOffset;
445 String getString(int start, int endDelta) => _sequence.subSequence(start, _cha rOffset + 1 + endDelta).toString();
446 int peek() {
447 if (_charOffset + 1 >= _sequence.length()) {
448 return -1;
449 }
450 return _sequence.charAt(_charOffset + 1);
451 }
452 void set offset(int offset) {
453 _charOffset = offset;
454 }
455 }
456 /**
457 * Instances of the class `IncrementalScanner` implement a scanner that scans a subset of a
458 * string and inserts the resulting tokens into the middle of an existing token stream.
459 *
460 * @coverage dart.engine.parser
461 */
462 class IncrementalScanner extends Scanner {
463
464 /**
465 * The reader used to access the characters in the source.
466 */
467 CharacterReader _reader;
468
469 /**
470 * A map from tokens that were copied to the copies of the tokens.
471 */
472 TokenMap _tokenMap = new TokenMap();
473
474 /**
475 * Initialize a newly created scanner.
476 *
477 * @param source the source being scanned
478 * @param reader the character reader used to read the characters in the sourc e
479 * @param errorListener the error listener that will be informed of any errors that are found
480 */
481 IncrementalScanner(Source source, CharacterReader reader, AnalysisErrorListene r errorListener) : super(source, reader, errorListener) {
482 this._reader = reader;
483 }
484
485 /**
486 * Given the stream of tokens scanned from the original source, the modified s ource (the result of
487 * replacing one contiguous range of characters with another string of charact ers), and a
488 * specification of the modification that was made, return a stream of tokens scanned from the
489 * modified source. The original stream of tokens will not be modified.
490 *
491 * @param originalStream the stream of tokens scanned from the original source
492 * @param index the index of the first character in both the original and modi fied source that was
493 * affected by the modification
494 * @param removedLength the number of characters removed from the original sou rce
495 * @param insertedLength the number of characters added to the modified source
496 */
497 Token rescan(Token originalStream, int index, int removedLength, int insertedL ength) {
498 while (originalStream.end < index) {
499 originalStream = copyAndAdvance(originalStream, 0);
500 }
501 int modifiedEnd = index + insertedLength - 1;
502 _reader.offset = Math.min(originalStream.offset, index) - 1;
503 int next = _reader.advance();
504 while (next != -1 && _reader.offset <= modifiedEnd) {
505 next = bigSwitch(next);
506 }
507 int removedEnd = index + removedLength - 1;
508 while (originalStream.offset <= removedEnd) {
509 originalStream = originalStream.next;
510 }
511 int delta = insertedLength - removedLength;
512 while (originalStream.type != TokenType.EOF) {
513 originalStream = copyAndAdvance(originalStream, delta);
514 }
515 copyAndAdvance(originalStream, delta);
516 return firstToken();
517 }
518 Token copyAndAdvance(Token originalToken, int delta) {
519 Token copiedToken = originalToken.copy();
520 _tokenMap.put(originalToken, copiedToken);
521 copiedToken.applyDelta(delta);
522 appendToken(copiedToken);
523 Token originalComment = originalToken.precedingComments;
524 Token copiedComment = originalToken.precedingComments;
525 while (originalComment != null) {
526 _tokenMap.put(originalComment, copiedComment);
527 originalComment = originalComment.next;
528 copiedComment = copiedComment.next;
529 }
530 return originalToken.next;
531 }
532 }
533 /**
534 * The class `Scanner` implements a scanner for Dart code.
535 *
536 * The lexical structure of Dart is ambiguous without knowledge of the context i n which a token is
537 * being scanned. For example, without context we cannot determine whether sourc e of the form "<<"
538 * should be scanned as a single left-shift operator or as two left angle bracke ts. This scanner
539 * does not have any context, so it always resolves such conflicts by scanning t he longest possible
540 * token.
541 *
542 * @coverage dart.engine.parser
543 */
544 class Scanner {
545
546 /**
547 * The source being scanned.
548 */
549 Source source;
550
551 /**
552 * The reader used to access the characters in the source.
553 */
554 CharacterReader _reader;
555
556 /**
557 * The error listener that will be informed of any errors that are found durin g the scan.
558 */
559 AnalysisErrorListener _errorListener;
560
561 /**
562 * The token pointing to the head of the linked list of tokens.
563 */
564 Token _tokens;
565
566 /**
567 * The last token that was scanned.
568 */
569 Token _tail;
570
571 /**
572 * The first token in the list of comment tokens found since the last non-comm ent token.
573 */
574 Token _firstComment;
575
576 /**
577 * The last token in the list of comment tokens found since the last non-comme nt token.
578 */
579 Token _lastComment;
580
581 /**
582 * The index of the first character of the current token.
583 */
584 int _tokenStart = 0;
585
586 /**
587 * A list containing the offsets of the first character of each line in the so urce code.
588 */
589 List<int> _lineStarts = new List<int>();
590
591 /**
592 * A list, treated something like a stack, of tokens representing the beginnin g of a matched pair.
593 * It is used to pair the end tokens with the begin tokens.
594 */
595 List<BeginToken> _groupingStack = new List<BeginToken>();
596
597 /**
598 * The index of the last item in the [groupingStack], or `-1` if the stack is empty.
599 */
600 int _stackEnd = -1;
601
602 /**
603 * A flag indicating whether any unmatched groups were found during the parse.
604 */
605 bool _hasUnmatchedGroups2 = false;
606
607 /**
608 * Initialize a newly created scanner.
609 *
610 * @param source the source being scanned
611 * @param reader the character reader used to read the characters in the sourc e
612 * @param errorListener the error listener that will be informed of any errors that are found
613 */
614 Scanner(Source source, CharacterReader reader, AnalysisErrorListener errorList ener) {
615 this.source = source;
616 this._reader = reader;
617 this._errorListener = errorListener;
618 _tokens = new Token(TokenType.EOF, -1);
619 _tokens.setNext(_tokens);
620 _tail = _tokens;
621 _tokenStart = -1;
622 _lineStarts.add(0);
623 }
624
625 /**
626 * Return an array containing the offsets of the first character of each line in the source code.
627 *
628 * @return an array containing the offsets of the first character of each line in the source code
629 */
630 List<int> get lineStarts => _lineStarts;
631
632 /**
633 * Return `true` if any unmatched groups were found during the parse.
634 *
635 * @return `true` if any unmatched groups were found during the parse
636 */
637 bool hasUnmatchedGroups() => _hasUnmatchedGroups2;
638
639 /**
640 * Record that the source begins on the given line and column at the current o ffset as given by
641 * the reader. The line starts for lines before the given line will not be cor rect.
642 *
643 * This method must be invoked at most one time and must be invoked before sca nning begins. The
644 * values provided must be sensible. The results are undefined if these condit ions are violated.
645 *
646 * @param line the one-based index of the line containing the first character of the source
647 * @param column the one-based index of the column in which the first characte r of the source
648 * occurs
649 */
650 void setSourceStart(int line, int column) {
651 int offset = _reader.offset;
652 if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
653 return;
654 }
655 for (int i = 2; i < line; i++) {
656 _lineStarts.add(1);
657 }
658 _lineStarts.add(offset - column + 1);
659 }
660
661 /**
662 * Scan the source code to produce a list of tokens representing the source.
663 *
664 * @return the first token in the list of tokens that were produced
665 */
666 Token tokenize() {
667 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.AbstractScanner.tokenize");
668 int tokenCounter = 0;
669 try {
670 int next = _reader.advance();
671 while (next != -1) {
672 tokenCounter++;
673 next = bigSwitch(next);
674 }
675 appendEofToken();
676 instrumentation.metric2("tokensCount", tokenCounter);
677 return firstToken();
678 } finally {
679 instrumentation.log2(2);
680 }
681 }
682
683 /**
684 * Append the given token to the end of the token stream being scanned. This m ethod is intended to
685 * be used by subclasses that copy existing tokens and should not normally be used because it will
686 * fail to correctly associate any comments with the token being passed in.
687 *
688 * @param token the token to be appended
689 */
690 void appendToken(Token token) {
691 _tail = _tail.setNext(token);
692 }
693 int bigSwitch(int next) {
694 beginToken();
695 if (next == 0xD) {
696 next = _reader.advance();
697 if (next == 0xA) {
698 next = _reader.advance();
699 }
700 recordStartOfLine();
701 return next;
702 } else if (next == 0xA) {
703 next = _reader.advance();
704 recordStartOfLine();
705 return next;
706 } else if (next == 0x9 || next == 0x20) {
707 return _reader.advance();
708 }
709 if (next == 0x72) {
710 int peek = _reader.peek();
711 if (peek == 0x22 || peek == 0x27) {
712 int start = _reader.offset;
713 return tokenizeString(_reader.advance(), start, true);
714 }
715 }
716 if (0x61 <= next && next <= 0x7A) {
717 return tokenizeKeywordOrIdentifier(next, true);
718 }
719 if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
720 return tokenizeIdentifier(next, _reader.offset, true);
721 }
722 if (next == 0x3C) {
723 return tokenizeLessThan(next);
724 }
725 if (next == 0x3E) {
726 return tokenizeGreaterThan(next);
727 }
728 if (next == 0x3D) {
729 return tokenizeEquals(next);
730 }
731 if (next == 0x21) {
732 return tokenizeExclamation(next);
733 }
734 if (next == 0x2B) {
735 return tokenizePlus(next);
736 }
737 if (next == 0x2D) {
738 return tokenizeMinus(next);
739 }
740 if (next == 0x2A) {
741 return tokenizeMultiply(next);
742 }
743 if (next == 0x25) {
744 return tokenizePercent(next);
745 }
746 if (next == 0x26) {
747 return tokenizeAmpersand(next);
748 }
749 if (next == 0x7C) {
750 return tokenizeBar(next);
751 }
752 if (next == 0x5E) {
753 return tokenizeCaret(next);
754 }
755 if (next == 0x5B) {
756 return tokenizeOpenSquareBracket(next);
757 }
758 if (next == 0x7E) {
759 return tokenizeTilde(next);
760 }
761 if (next == 0x5C) {
762 appendToken2(TokenType.BACKSLASH);
763 return _reader.advance();
764 }
765 if (next == 0x23) {
766 return tokenizeTag(next);
767 }
768 if (next == 0x28) {
769 appendBeginToken(TokenType.OPEN_PAREN);
770 return _reader.advance();
771 }
772 if (next == 0x29) {
773 appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
774 return _reader.advance();
775 }
776 if (next == 0x2C) {
777 appendToken2(TokenType.COMMA);
778 return _reader.advance();
779 }
780 if (next == 0x3A) {
781 appendToken2(TokenType.COLON);
782 return _reader.advance();
783 }
784 if (next == 0x3B) {
785 appendToken2(TokenType.SEMICOLON);
786 return _reader.advance();
787 }
788 if (next == 0x3F) {
789 appendToken2(TokenType.QUESTION);
790 return _reader.advance();
791 }
792 if (next == 0x5D) {
793 appendEndToken(TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACK ET);
794 return _reader.advance();
795 }
796 if (next == 0x60) {
797 appendToken2(TokenType.BACKPING);
798 return _reader.advance();
799 }
800 if (next == 0x7B) {
801 appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
802 return _reader.advance();
803 }
804 if (next == 0x7D) {
805 appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET );
806 return _reader.advance();
807 }
808 if (next == 0x2F) {
809 return tokenizeSlashOrComment(next);
810 }
811 if (next == 0x40) {
812 appendToken2(TokenType.AT);
813 return _reader.advance();
814 }
815 if (next == 0x22 || next == 0x27) {
816 return tokenizeString(next, _reader.offset, false);
817 }
818 if (next == 0x2E) {
819 return tokenizeDotOrNumber(next);
820 }
821 if (next == 0x30) {
822 return tokenizeHexOrNumber(next);
823 }
824 if (0x31 <= next && next <= 0x39) {
825 return tokenizeNumber(next);
826 }
827 if (next == -1) {
828 return -1;
829 }
830 reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
831 return _reader.advance();
832 }
833
834 /**
835 * Return the first token in the token stream that was scanned.
836 *
837 * @return the first token in the token stream that was scanned
838 */
839 Token firstToken() => _tokens.next;
840
841 /**
842 * Record the fact that we are at the beginning of a new line in the source.
843 */
844 void recordStartOfLine() {
845 _lineStarts.add(_reader.offset);
846 }
847 void appendBeginToken(TokenType type) {
848 BeginToken token;
849 if (_firstComment == null) {
850 token = new BeginToken(type, _tokenStart);
851 } else {
852 token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
853 _firstComment = null;
854 _lastComment = null;
855 }
856 _tail = _tail.setNext(token);
857 _groupingStack.add(token);
858 _stackEnd++;
859 }
860 void appendCommentToken(TokenType type, String value) {
861 if (_firstComment == null) {
862 _firstComment = new StringToken(type, value, _tokenStart);
863 _lastComment = _firstComment;
864 } else {
865 _lastComment = _lastComment.setNext(new StringToken(type, value, _tokenSta rt));
866 }
867 }
868 void appendEndToken(TokenType type, TokenType beginType) {
869 Token token;
870 if (_firstComment == null) {
871 token = new Token(type, _tokenStart);
872 } else {
873 token = new TokenWithComment(type, _tokenStart, _firstComment);
874 _firstComment = null;
875 _lastComment = null;
876 }
877 _tail = _tail.setNext(token);
878 if (_stackEnd >= 0) {
879 BeginToken begin = _groupingStack[_stackEnd];
880 if (identical(begin.type, beginType)) {
881 begin.endToken = token;
882 _groupingStack.removeAt(_stackEnd--);
883 }
884 }
885 }
886 void appendEofToken() {
887 Token eofToken;
888 if (_firstComment == null) {
889 eofToken = new Token(TokenType.EOF, _reader.offset + 1);
890 } else {
891 eofToken = new TokenWithComment(TokenType.EOF, _reader.offset + 1, _firstC omment);
892 _firstComment = null;
893 _lastComment = null;
894 }
895 eofToken.setNext(eofToken);
896 _tail = _tail.setNext(eofToken);
897 if (_stackEnd >= 0) {
898 _hasUnmatchedGroups2 = true;
899 }
900 }
901 void appendKeywordToken(Keyword keyword) {
902 if (_firstComment == null) {
903 _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
904 } else {
905 _tail = _tail.setNext(new KeywordTokenWithComment(keyword, _tokenStart, _f irstComment));
906 _firstComment = null;
907 _lastComment = null;
908 }
909 }
910 void appendStringToken(TokenType type, String value) {
911 if (_firstComment == null) {
912 _tail = _tail.setNext(new StringToken(type, value, _tokenStart));
913 } else {
914 _tail = _tail.setNext(new StringTokenWithComment(type, value, _tokenStart, _firstComment));
915 _firstComment = null;
916 _lastComment = null;
917 }
918 }
919 void appendStringToken2(TokenType type, String value, int offset) {
920 if (_firstComment == null) {
921 _tail = _tail.setNext(new StringToken(type, value, _tokenStart + offset));
922 } else {
923 _tail = _tail.setNext(new StringTokenWithComment(type, value, _tokenStart + offset, _firstComment));
924 _firstComment = null;
925 _lastComment = null;
926 }
927 }
928 void appendToken2(TokenType type) {
929 if (_firstComment == null) {
930 _tail = _tail.setNext(new Token(type, _tokenStart));
931 } else {
932 _tail = _tail.setNext(new TokenWithComment(type, _tokenStart, _firstCommen t));
933 _firstComment = null;
934 _lastComment = null;
935 }
936 }
937 void appendToken3(TokenType type, int offset) {
938 if (_firstComment == null) {
939 _tail = _tail.setNext(new Token(type, offset));
940 } else {
941 _tail = _tail.setNext(new TokenWithComment(type, offset, _firstComment));
942 _firstComment = null;
943 _lastComment = null;
944 }
945 }
946 void beginToken() {
947 _tokenStart = _reader.offset;
948 }
949
950 /**
951 * Return the beginning token corresponding to a closing brace that was found while scanning
952 * inside a string interpolation expression. Tokens that cannot be matched wit h the closing brace
953 * will be dropped from the stack.
954 *
955 * @return the token to be paired with the closing brace
956 */
957 BeginToken findTokenMatchingClosingBraceInInterpolationExpression() {
958 while (_stackEnd >= 0) {
959 BeginToken begin = _groupingStack[_stackEnd];
960 if (identical(begin.type, TokenType.OPEN_CURLY_BRACKET) || identical(begin .type, TokenType.STRING_INTERPOLATION_EXPRESSION)) {
961 return begin;
962 }
963 _hasUnmatchedGroups2 = true;
964 _groupingStack.removeAt(_stackEnd--);
965 }
966 return null;
967 }
968
969 /**
970 * Report an error at the current offset.
971 *
972 * @param errorCode the error code indicating the nature of the error
973 * @param arguments any arguments needed to complete the error message
974 */
975 void reportError(ScannerErrorCode errorCode, List<Object> arguments) {
976 _errorListener.onError(new AnalysisError.con2(source, _reader.offset, 1, err orCode, arguments));
977 }
978 int select(int choice, TokenType yesType, TokenType noType) {
979 int next = _reader.advance();
980 if (next == choice) {
981 appendToken2(yesType);
982 return _reader.advance();
983 } else {
984 appendToken2(noType);
985 return next;
986 }
987 }
988 int select2(int choice, TokenType yesType, TokenType noType, int offset) {
989 int next = _reader.advance();
990 if (next == choice) {
991 appendToken3(yesType, offset);
992 return _reader.advance();
993 } else {
994 appendToken3(noType, offset);
995 return next;
996 }
997 }
998 int tokenizeAmpersand(int next) {
999 next = _reader.advance();
1000 if (next == 0x26) {
1001 appendToken2(TokenType.AMPERSAND_AMPERSAND);
1002 return _reader.advance();
1003 } else if (next == 0x3D) {
1004 appendToken2(TokenType.AMPERSAND_EQ);
1005 return _reader.advance();
1006 } else {
1007 appendToken2(TokenType.AMPERSAND);
1008 return next;
1009 }
1010 }
1011 int tokenizeBar(int next) {
1012 next = _reader.advance();
1013 if (next == 0x7C) {
1014 appendToken2(TokenType.BAR_BAR);
1015 return _reader.advance();
1016 } else if (next == 0x3D) {
1017 appendToken2(TokenType.BAR_EQ);
1018 return _reader.advance();
1019 } else {
1020 appendToken2(TokenType.BAR);
1021 return next;
1022 }
1023 }
1024 int tokenizeCaret(int next) => select(0x3D, TokenType.CARET_EQ, TokenType.CARE T);
1025 int tokenizeDotOrNumber(int next) {
1026 int start = _reader.offset;
1027 next = _reader.advance();
1028 if (0x30 <= next && next <= 0x39) {
1029 return tokenizeFractionPart(next, start);
1030 } else if (0x2E == next) {
1031 return select(0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIO D);
1032 } else {
1033 appendToken2(TokenType.PERIOD);
1034 return next;
1035 }
1036 }
1037 int tokenizeEquals(int next) {
1038 next = _reader.advance();
1039 if (next == 0x3D) {
1040 appendToken2(TokenType.EQ_EQ);
1041 return _reader.advance();
1042 } else if (next == 0x3E) {
1043 appendToken2(TokenType.FUNCTION);
1044 return _reader.advance();
1045 }
1046 appendToken2(TokenType.EQ);
1047 return next;
1048 }
1049 int tokenizeExclamation(int next) {
1050 next = _reader.advance();
1051 if (next == 0x3D) {
1052 appendToken2(TokenType.BANG_EQ);
1053 return _reader.advance();
1054 }
1055 appendToken2(TokenType.BANG);
1056 return next;
1057 }
1058 int tokenizeExponent(int next) {
1059 if (next == 0x2B || next == 0x2D) {
1060 next = _reader.advance();
1061 }
1062 bool hasDigits = false;
1063 while (true) {
1064 if (0x30 <= next && next <= 0x39) {
1065 hasDigits = true;
1066 } else {
1067 if (!hasDigits) {
1068 reportError(ScannerErrorCode.MISSING_DIGIT, []);
1069 }
1070 return next;
1071 }
1072 next = _reader.advance();
1073 }
1074 }
1075 int tokenizeFractionPart(int next, int start) {
1076 bool done = false;
1077 bool hasDigit = false;
1078 LOOP: while (!done) {
1079 if (0x30 <= next && next <= 0x39) {
1080 hasDigit = true;
1081 } else if (0x65 == next || 0x45 == next) {
1082 hasDigit = true;
1083 next = tokenizeExponent(_reader.advance());
1084 done = true;
1085 continue LOOP;
1086 } else {
1087 done = true;
1088 continue LOOP;
1089 }
1090 next = _reader.advance();
1091 }
1092 if (!hasDigit) {
1093 appendStringToken(TokenType.INT, _reader.getString(start, -2));
1094 if (0x2E == next) {
1095 return select2(0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PE RIOD, _reader.offset - 1);
1096 }
1097 appendToken3(TokenType.PERIOD, _reader.offset - 1);
1098 return bigSwitch(next);
1099 }
1100 appendStringToken(TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1));
1101 return next;
1102 }
1103 int tokenizeGreaterThan(int next) {
1104 next = _reader.advance();
1105 if (0x3D == next) {
1106 appendToken2(TokenType.GT_EQ);
1107 return _reader.advance();
1108 } else if (0x3E == next) {
1109 next = _reader.advance();
1110 if (0x3D == next) {
1111 appendToken2(TokenType.GT_GT_EQ);
1112 return _reader.advance();
1113 } else {
1114 appendToken2(TokenType.GT_GT);
1115 return next;
1116 }
1117 } else {
1118 appendToken2(TokenType.GT);
1119 return next;
1120 }
1121 }
1122 int tokenizeHex(int next) {
1123 int start = _reader.offset - 1;
1124 bool hasDigits = false;
1125 while (true) {
1126 next = _reader.advance();
1127 if ((0x30 <= next && next <= 0x39) || (0x41 <= next && next <= 0x46) || (0 x61 <= next && next <= 0x66)) {
1128 hasDigits = true;
1129 } else {
1130 if (!hasDigits) {
1131 reportError(ScannerErrorCode.MISSING_HEX_DIGIT, []);
1132 }
1133 appendStringToken(TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1));
1134 return next;
1135 }
1136 }
1137 }
1138 int tokenizeHexOrNumber(int next) {
1139 int x = _reader.peek();
1140 if (x == 0x78 || x == 0x58) {
1141 _reader.advance();
1142 return tokenizeHex(x);
1143 }
1144 return tokenizeNumber(next);
1145 }
1146 int tokenizeIdentifier(int next, int start, bool allowDollar) {
1147 while ((0x61 <= next && next <= 0x7A) || (0x41 <= next && next <= 0x5A) || ( 0x30 <= next && next <= 0x39) || next == 0x5F || (next == 0x24 && allowDollar)) {
1148 next = _reader.advance();
1149 }
1150 appendStringToken(TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1));
1151 return next;
1152 }
1153 int tokenizeInterpolatedExpression(int next, int start) {
1154 appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
1155 next = _reader.advance();
1156 while (next != -1) {
1157 if (next == 0x7D) {
1158 BeginToken begin = findTokenMatchingClosingBraceInInterpolationExpressio n();
1159 if (begin == null) {
1160 beginToken();
1161 appendToken2(TokenType.CLOSE_CURLY_BRACKET);
1162 next = _reader.advance();
1163 beginToken();
1164 return next;
1165 } else if (identical(begin.type, TokenType.OPEN_CURLY_BRACKET)) {
1166 beginToken();
1167 appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRA CKET);
1168 next = _reader.advance();
1169 beginToken();
1170 } else if (identical(begin.type, TokenType.STRING_INTERPOLATION_EXPRESSI ON)) {
1171 beginToken();
1172 appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.STRING_INTERPO LATION_EXPRESSION);
1173 next = _reader.advance();
1174 beginToken();
1175 return next;
1176 }
1177 } else {
1178 next = bigSwitch(next);
1179 }
1180 }
1181 if (next == -1) {
1182 return next;
1183 }
1184 next = _reader.advance();
1185 beginToken();
1186 return next;
1187 }
1188 int tokenizeInterpolatedIdentifier(int next, int start) {
1189 appendStringToken2(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
1190 if ((0x41 <= next && next <= 0x5A) || (0x61 <= next && next <= 0x7A) || next == 0x5F) {
1191 beginToken();
1192 next = tokenizeKeywordOrIdentifier(next, false);
1193 }
1194 beginToken();
1195 return next;
1196 }
1197 int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
1198 KeywordState state = KeywordState.KEYWORD_STATE;
1199 int start = _reader.offset;
1200 while (state != null && 0x61 <= next && next <= 0x7A) {
1201 state = state.next(next as int);
1202 next = _reader.advance();
1203 }
1204 if (state == null || state.keyword() == null) {
1205 return tokenizeIdentifier(next, start, allowDollar);
1206 }
1207 if ((0x41 <= next && next <= 0x5A) || (0x30 <= next && next <= 0x39) || next == 0x5F || next == 0x24) {
1208 return tokenizeIdentifier(next, start, allowDollar);
1209 } else if (next < 128) {
1210 appendKeywordToken(state.keyword());
1211 return next;
1212 } else {
1213 return tokenizeIdentifier(next, start, allowDollar);
1214 }
1215 }
1216 int tokenizeLessThan(int next) {
1217 next = _reader.advance();
1218 if (0x3D == next) {
1219 appendToken2(TokenType.LT_EQ);
1220 return _reader.advance();
1221 } else if (0x3C == next) {
1222 return select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT);
1223 } else {
1224 appendToken2(TokenType.LT);
1225 return next;
1226 }
1227 }
1228 int tokenizeMinus(int next) {
1229 next = _reader.advance();
1230 if (next == 0x2D) {
1231 appendToken2(TokenType.MINUS_MINUS);
1232 return _reader.advance();
1233 } else if (next == 0x3D) {
1234 appendToken2(TokenType.MINUS_EQ);
1235 return _reader.advance();
1236 } else {
1237 appendToken2(TokenType.MINUS);
1238 return next;
1239 }
1240 }
1241 int tokenizeMultiLineComment(int next) {
1242 int nesting = 1;
1243 next = _reader.advance();
1244 while (true) {
1245 if (-1 == next) {
1246 reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, []);
1247 appendCommentToken(TokenType.MULTI_LINE_COMMENT, _reader.getString(_toke nStart, 0));
1248 return next;
1249 } else if (0x2A == next) {
1250 next = _reader.advance();
1251 if (0x2F == next) {
1252 --nesting;
1253 if (0 == nesting) {
1254 appendCommentToken(TokenType.MULTI_LINE_COMMENT, _reader.getString(_ tokenStart, 0));
1255 return _reader.advance();
1256 } else {
1257 next = _reader.advance();
1258 }
1259 }
1260 } else if (0x2F == next) {
1261 next = _reader.advance();
1262 if (0x2A == next) {
1263 next = _reader.advance();
1264 ++nesting;
1265 }
1266 } else if (next == 0xD) {
1267 next = _reader.advance();
1268 if (next == 0xA) {
1269 next = _reader.advance();
1270 }
1271 recordStartOfLine();
1272 } else if (next == 0xA) {
1273 recordStartOfLine();
1274 next = _reader.advance();
1275 } else {
1276 next = _reader.advance();
1277 }
1278 }
1279 }
1280 int tokenizeMultiLineRawString(int quoteChar, int start) {
1281 int next = _reader.advance();
1282 outer: while (next != -1) {
1283 while (next != quoteChar) {
1284 next = _reader.advance();
1285 if (next == -1) {
1286 break outer;
1287 } else if (next == 0xD) {
1288 next = _reader.advance();
1289 if (next == 0xA) {
1290 next = _reader.advance();
1291 }
1292 recordStartOfLine();
1293 } else if (next == 0xA) {
1294 recordStartOfLine();
1295 next = _reader.advance();
1296 }
1297 }
1298 next = _reader.advance();
1299 if (next == quoteChar) {
1300 next = _reader.advance();
1301 if (next == quoteChar) {
1302 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1303 return _reader.advance();
1304 }
1305 }
1306 }
1307 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1308 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1309 return _reader.advance();
1310 }
1311 int tokenizeMultiLineString(int quoteChar, int start, bool raw) {
1312 if (raw) {
1313 return tokenizeMultiLineRawString(quoteChar, start);
1314 }
1315 int next = _reader.advance();
1316 while (next != -1) {
1317 if (next == 0x24) {
1318 appendStringToken(TokenType.STRING, _reader.getString(start, -1));
1319 beginToken();
1320 next = tokenizeStringInterpolation(start);
1321 start = _reader.offset;
1322 continue;
1323 }
1324 if (next == quoteChar) {
1325 next = _reader.advance();
1326 if (next == quoteChar) {
1327 next = _reader.advance();
1328 if (next == quoteChar) {
1329 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1330 return _reader.advance();
1331 }
1332 }
1333 continue;
1334 }
1335 if (next == 0x5C) {
1336 next = _reader.advance();
1337 if (next == -1) {
1338 break;
1339 }
1340 bool missingCharacter = false;
1341 if (next == 0xD) {
1342 missingCharacter = true;
1343 next = _reader.advance();
1344 if (next == 0xA) {
1345 next = _reader.advance();
1346 }
1347 recordStartOfLine();
1348 } else if (next == 0xA) {
1349 missingCharacter = true;
1350 recordStartOfLine();
1351 next = _reader.advance();
1352 } else {
1353 next = _reader.advance();
1354 }
1355 if (missingCharacter) {
1356 _errorListener.onError(new AnalysisError.con2(source, _reader.offset - 1, 1, ScannerErrorCode.CHARACTER_EXPECTED_AFTER_SLASH, []));
1357 }
1358 } else if (next == 0xD) {
1359 next = _reader.advance();
1360 if (next == 0xA) {
1361 next = _reader.advance();
1362 }
1363 recordStartOfLine();
1364 } else if (next == 0xA) {
1365 recordStartOfLine();
1366 next = _reader.advance();
1367 } else {
1368 next = _reader.advance();
1369 }
1370 }
1371 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1372 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1373 return _reader.advance();
1374 }
1375 int tokenizeMultiply(int next) => select(0x3D, TokenType.STAR_EQ, TokenType.ST AR);
1376 int tokenizeNumber(int next) {
1377 int start = _reader.offset;
1378 while (true) {
1379 next = _reader.advance();
1380 if (0x30 <= next && next <= 0x39) {
1381 continue;
1382 } else if (next == 0x2E) {
1383 return tokenizeFractionPart(_reader.advance(), start);
1384 } else if (next == 0x65 || next == 0x45) {
1385 return tokenizeFractionPart(next, start);
1386 } else {
1387 appendStringToken(TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1));
1388 return next;
1389 }
1390 }
1391 }
1392 int tokenizeOpenSquareBracket(int next) {
1393 next = _reader.advance();
1394 if (next == 0x5D) {
1395 return select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
1396 } else {
1397 appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
1398 return next;
1399 }
1400 }
1401 int tokenizePercent(int next) => select(0x3D, TokenType.PERCENT_EQ, TokenType. PERCENT);
1402 int tokenizePlus(int next) {
1403 next = _reader.advance();
1404 if (0x2B == next) {
1405 appendToken2(TokenType.PLUS_PLUS);
1406 return _reader.advance();
1407 } else if (0x3D == next) {
1408 appendToken2(TokenType.PLUS_EQ);
1409 return _reader.advance();
1410 } else {
1411 appendToken2(TokenType.PLUS);
1412 return next;
1413 }
1414 }
1415 int tokenizeSingleLineComment(int next) {
1416 while (true) {
1417 next = _reader.advance();
1418 if (-1 == next) {
1419 appendCommentToken(TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tok enStart, 0));
1420 return next;
1421 } else if (0xA == next || 0xD == next) {
1422 appendCommentToken(TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tok enStart, -1));
1423 return next;
1424 }
1425 }
1426 }
1427 int tokenizeSingleLineRawString(int next, int quoteChar, int start) {
1428 next = _reader.advance();
1429 while (next != -1) {
1430 if (next == quoteChar) {
1431 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1432 return _reader.advance();
1433 } else if (next == 0xD || next == 0xA) {
1434 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1435 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1436 return _reader.advance();
1437 }
1438 next = _reader.advance();
1439 }
1440 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1441 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1442 return _reader.advance();
1443 }
1444 int tokenizeSingleLineString(int next, int quoteChar, int start) {
1445 while (next != quoteChar) {
1446 if (next == 0x5C) {
1447 next = _reader.advance();
1448 } else if (next == 0x24) {
1449 appendStringToken(TokenType.STRING, _reader.getString(start, -1));
1450 beginToken();
1451 next = tokenizeStringInterpolation(start);
1452 start = _reader.offset;
1453 continue;
1454 }
1455 if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
1456 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1457 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1458 return _reader.advance();
1459 }
1460 next = _reader.advance();
1461 }
1462 appendStringToken(TokenType.STRING, _reader.getString(start, 0));
1463 return _reader.advance();
1464 }
1465 int tokenizeSlashOrComment(int next) {
1466 next = _reader.advance();
1467 if (0x2A == next) {
1468 return tokenizeMultiLineComment(next);
1469 } else if (0x2F == next) {
1470 return tokenizeSingleLineComment(next);
1471 } else if (0x3D == next) {
1472 appendToken2(TokenType.SLASH_EQ);
1473 return _reader.advance();
1474 } else {
1475 appendToken2(TokenType.SLASH);
1476 return next;
1477 }
1478 }
1479 int tokenizeString(int next, int start, bool raw) {
1480 int quoteChar = next;
1481 next = _reader.advance();
1482 if (quoteChar == next) {
1483 next = _reader.advance();
1484 if (quoteChar == next) {
1485 return tokenizeMultiLineString(quoteChar, start, raw);
1486 } else {
1487 appendStringToken(TokenType.STRING, _reader.getString(start, -1));
1488 return next;
1489 }
1490 }
1491 if (raw) {
1492 return tokenizeSingleLineRawString(next, quoteChar, start);
1493 } else {
1494 return tokenizeSingleLineString(next, quoteChar, start);
1495 }
1496 }
1497 int tokenizeStringInterpolation(int start) {
1498 beginToken();
1499 int next = _reader.advance();
1500 if (next == 0x7B) {
1501 return tokenizeInterpolatedExpression(next, start);
1502 } else {
1503 return tokenizeInterpolatedIdentifier(next, start);
1504 }
1505 }
1506 int tokenizeTag(int next) {
1507 if (_reader.offset == 0) {
1508 if (_reader.peek() == 0x21) {
1509 do {
1510 next = _reader.advance();
1511 } while (next != 0xA && next != 0xD && next > 0);
1512 appendStringToken(TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0 ));
1513 return next;
1514 }
1515 }
1516 appendToken2(TokenType.HASH);
1517 return _reader.advance();
1518 }
1519 int tokenizeTilde(int next) {
1520 next = _reader.advance();
1521 if (next == 0x2F) {
1522 return select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
1523 } else {
1524 appendToken2(TokenType.TILDE);
1525 return next;
1526 }
1527 }
1528 }
1529 /**
1530 * Instances of the class `StringToken` represent a token whose value is indepen dent of it's
1531 * type.
1532 *
1533 * @coverage dart.engine.parser
1534 */
1535 class StringToken extends Token {
1536
1537 /**
1538 * The lexeme represented by this token.
1539 */
1540 String _value2;
1541
1542 /**
1543 * Initialize a newly created token to represent a token of the given type wit h the given value.
1544 *
1545 * @param type the type of the token
1546 * @param value the lexeme represented by this token
1547 * @param offset the offset from the beginning of the file to the first charac ter in the token
1548 */
1549 StringToken(TokenType type, String value, int offset) : super(type, offset) {
1550 this._value2 = StringUtilities.intern(value);
1551 }
1552 Token copy() => new StringToken(type, _value2, offset);
1553 String get lexeme => _value2;
1554 String value() => _value2;
1555 }
1556 /**
1557 * Instances of the class `TokenWithComment` represent a normal token that is pr eceded by
1558 * comments.
1559 *
1560 * @coverage dart.engine.parser
1561 */
1562 class TokenWithComment extends Token {
1563
1564 /**
1565 * The first comment in the list of comments that precede this token.
1566 */
1567 Token _precedingComment;
1568
1569 /**
1570 * Initialize a newly created token to have the given type and offset and to b e preceded by the
1571 * comments reachable from the given comment.
1572 *
1573 * @param type the type of the token
1574 * @param offset the offset from the beginning of the file to the first charac ter in the token
1575 * @param precedingComment the first comment in the list of comments that prec ede this token
1576 */
1577 TokenWithComment(TokenType type, int offset, Token precedingComment) : super(t ype, offset) {
1578 this._precedingComment = precedingComment;
1579 }
1580 Token copy() => new TokenWithComment(type, offset, _precedingComment);
1581 Token get precedingComments => _precedingComment;
1582 }
1583 /**
1584 * Instances of the class `Token` represent a token that was scanned from the in put. Each
1585 * token knows which token follows it, acting as the head of a linked list of to kens.
1586 *
1587 * @coverage dart.engine.parser
1588 */
1589 class Token {
1590
1591 /**
1592 * The type of the token.
1593 */
1594 TokenType type;
1595
1596 /**
1597 * The offset from the beginning of the file to the first character in the tok en.
1598 */
1599 int offset = 0;
1600
1601 /**
1602 * The previous token in the token stream.
1603 */
1604 Token previous;
1605
1606 /**
1607 * The next token in the token stream.
1608 */
1609 Token next;
1610
1611 /**
1612 * Initialize a newly created token to have the given type and offset.
1613 *
1614 * @param type the type of the token
1615 * @param offset the offset from the beginning of the file to the first charac ter in the token
1616 */
1617 Token(TokenType type, int offset) {
1618 this.type = type;
1619 this.offset = offset;
1620 }
1621
1622 /**
1623 * Return a newly created token that is a copy of this token but that is not a part of any token
1624 * stream.
1625 *
1626 * @return a newly created token that is a copy of this token
1627 */
1628 Token copy() => new Token(type, offset);
1629
1630 /**
1631 * Return the offset from the beginning of the file to the character after las t character of the
1632 * token.
1633 *
1634 * @return the offset from the beginning of the file to the first character af ter last character
1635 * of the token
1636 */
1637 int get end => offset + length;
1638
1639 /**
1640 * Return the number of characters in the node's source range.
1641 *
1642 * @return the number of characters in the node's source range
1643 */
1644 int get length => lexeme.length;
1645
1646 /**
1647 * Return the lexeme that represents this token.
1648 *
1649 * @return the lexeme that represents this token
1650 */
1651 String get lexeme => type.lexeme;
1652
1653 /**
1654 * Return the first comment in the list of comments that precede this token, o r `null` if
1655 * there are no comments preceding this token. Additional comments can be reac hed by following the
1656 * token stream using [getNext] until `null` is returned.
1657 *
1658 * @return the first comment in the list of comments that precede this token
1659 */
1660 Token get precedingComments => null;
1661
1662 /**
1663 * Return `true` if this token represents an operator.
1664 *
1665 * @return `true` if this token represents an operator
1666 */
1667 bool get isOperator => type.isOperator;
1668
1669 /**
1670 * Return `true` if this token is a synthetic token. A synthetic token is a to ken that was
1671 * introduced by the parser in order to recover from an error in the code. Syn thetic tokens always
1672 * have a length of zero (`0`).
1673 *
1674 * @return `true` if this token is a synthetic token
1675 */
1676 bool get isSynthetic => length == 0;
1677
1678 /**
1679 * Return `true` if this token represents an operator that can be defined by u sers.
1680 *
1681 * @return `true` if this token represents an operator that can be defined by users
1682 */
1683 bool get isUserDefinableOperator => type.isUserDefinableOperator;
1684
1685 /**
1686 * Set the next token in the token stream to the given token. This has the sid e-effect of setting
1687 * this token to be the previous token for the given token.
1688 *
1689 * @param token the next token in the token stream
1690 * @return the token that was passed in
1691 */
1692 Token setNext(Token token) {
1693 next = token;
1694 token.previous = this;
1695 return token;
1696 }
1697
1698 /**
1699 * Set the next token in the token stream to the given token without changing which token is the
1700 * previous token for the given token.
1701 *
1702 * @param token the next token in the token stream
1703 * @return the token that was passed in
1704 */
1705 Token setNextWithoutSettingPrevious(Token token) {
1706 next = token;
1707 return token;
1708 }
1709 String toString() => lexeme;
1710
1711 /**
1712 * Return the value of this token. For keyword tokens, this is the keyword ass ociated with the
1713 * token, for other tokens it is the lexeme associated with the token.
1714 *
1715 * @return the value of this token
1716 */
1717 Object value() => type.lexeme;
1718
1719 /**
1720 * Apply (add) the given delta to this token's offset.
1721 *
1722 * @param delta the amount by which the offset is to be adjusted
1723 */
1724 void applyDelta(int delta) {
1725 offset += delta;
1726 }
1727
1728 /**
1729 * Copy a linked list of comment tokens identical to the given comment tokens.
1730 *
1731 * @param token the first token in the list, or `null` if there are no tokens to be copied
1732 * @return the tokens that were created
1733 */
1734 Token copyComments(Token token) {
1735 if (token == null) {
1736 return null;
1737 }
1738 Token head = token.copy();
1739 Token tail = head;
1740 token = token.next;
1741 while (token != null) {
1742 tail = tail.setNext(token.copy());
1743 }
1744 return head;
1745 }
1746 }
1747 /**
1748 * The interface `CharacterReader`
1749 */
1750 abstract class CharacterReader {
1751
1752 /**
1753 * Advance the current position and return the character at the new current po sition.
1754 *
1755 * @return the character at the new current position
1756 */
1757 int advance();
1758
1759 /**
1760 * Return the current offset relative to the beginning of the source. Return t he initial offset if
1761 * the scanner has not yet scanned the source code, and one (1) past the end o f the source code if
1762 * the entire source code has been scanned.
1763 *
1764 * @return the current offset of the scanner in the source
1765 */
1766 int get offset;
1767
1768 /**
1769 * Return the substring of the source code between the start offset and the mo dified current
1770 * position. The current position is modified by adding the end delta.
1771 *
1772 * @param start the offset to the beginning of the string, relative to the sta rt of the file
1773 * @param endDelta the number of characters after the current location to be i ncluded in the
1774 * string, or the number of characters before the current location to be excluded if the
1775 * offset is negative
1776 * @return the specified substring of the source code
1777 */
1778 String getString(int start, int endDelta);
1779
1780 /**
1781 * Return the character at the current position without changing the current p osition.
1782 *
1783 * @return the character at the current position
1784 */
1785 int peek();
1786
1787 /**
1788 * Set the current offset relative to the beginning of the source. The new off set must be between
1789 * the initial offset and one (1) past the end of the source code.
1790 *
1791 * @param offset the new offset in the source
1792 */
1793 void set offset(int offset);
1794 }
1795 /**
1796 * Instances of the class `BeginTokenWithComment` represent a begin token that i s preceded by
1797 * comments.
1798 *
1799 * @coverage dart.engine.parser
1800 */
1801 class BeginTokenWithComment extends BeginToken {
1802
1803 /**
1804 * The first comment in the list of comments that precede this token.
1805 */
1806 Token _precedingComment;
1807
1808 /**
1809 * Initialize a newly created token to have the given type and offset and to b e preceded by the
1810 * comments reachable from the given comment.
1811 *
1812 * @param type the type of the token
1813 * @param offset the offset from the beginning of the file to the first charac ter in the token
1814 * @param precedingComment the first comment in the list of comments that prec ede this token
1815 */
1816 BeginTokenWithComment(TokenType type, int offset, Token precedingComment) : su per(type, offset) {
1817 this._precedingComment = precedingComment;
1818 }
1819 Token copy() => new BeginTokenWithComment(type, offset, copyComments(_precedin gComment));
1820 Token get precedingComments => _precedingComment;
1821 void applyDelta(int delta) {
1822 super.applyDelta(delta);
1823 Token token = _precedingComment;
1824 while (token != null) {
1825 token.applyDelta(delta);
1826 token = token.next;
1827 }
1828 }
1829 }
1830 /**
1831 * Instances of the class `KeywordToken` represent a keyword in the language.
1832 *
1833 * @coverage dart.engine.parser
1834 */
1835 class KeywordToken extends Token {
1836
1837 /**
1838 * The keyword being represented by this token.
1839 */
1840 Keyword keyword;
1841
1842 /**
1843 * Initialize a newly created token to represent the given keyword.
1844 *
1845 * @param keyword the keyword being represented by this token
1846 * @param offset the offset from the beginning of the file to the first charac ter in the token
1847 */
1848 KeywordToken(Keyword keyword, int offset) : super(TokenType.KEYWORD, offset) {
1849 this.keyword = keyword;
1850 }
1851 Token copy() => new KeywordToken(keyword, offset);
1852 String get lexeme => keyword.syntax;
1853 Keyword value() => keyword;
1854 }
1855 /**
1856 * Instances of the class `BeginToken` represent the opening half of a grouping pair of
1857 * tokens. This is used for curly brackets ('{'), parentheses ('('), and square brackets ('[').
1858 *
1859 * @coverage dart.engine.parser
1860 */
1861 class BeginToken extends Token {
1862
1863 /**
1864 * The token that corresponds to this token.
1865 */
1866 Token endToken;
1867
1868 /**
1869 * Initialize a newly created token representing the opening half of a groupin g pair of tokens.
1870 *
1871 * @param type the type of the token
1872 * @param offset the offset from the beginning of the file to the first charac ter in the token
1873 */
1874 BeginToken(TokenType type, int offset) : super(type, offset) {
1875 assert((identical(type, TokenType.OPEN_CURLY_BRACKET) || identical(type, Tok enType.OPEN_PAREN) || identical(type, TokenType.OPEN_SQUARE_BRACKET) || identica l(type, TokenType.STRING_INTERPOLATION_EXPRESSION)));
1876 }
1877 Token copy() => new BeginToken(type, offset);
1878 }
1879 /**
1880 * The enumeration `TokenClass` represents classes (or groups) of tokens with a similar use.
1881 *
1882 * @coverage dart.engine.parser
1883 */
1884 class TokenClass extends Enum<TokenClass> {
1885
1886 /**
1887 * A value used to indicate that the token type is not part of any specific cl ass of token.
1888 */
1889 static final TokenClass NO_CLASS = new TokenClass.con1('NO_CLASS', 0);
1890
1891 /**
1892 * A value used to indicate that the token type is an additive operator.
1893 */
1894 static final TokenClass ADDITIVE_OPERATOR = new TokenClass.con2('ADDITIVE_OPER ATOR', 1, 12);
1895
1896 /**
1897 * A value used to indicate that the token type is an assignment operator.
1898 */
1899 static final TokenClass ASSIGNMENT_OPERATOR = new TokenClass.con2('ASSIGNMENT_ OPERATOR', 2, 1);
1900
1901 /**
1902 * A value used to indicate that the token type is a bitwise-and operator.
1903 */
1904 static final TokenClass BITWISE_AND_OPERATOR = new TokenClass.con2('BITWISE_AN D_OPERATOR', 3, 8);
1905
1906 /**
1907 * A value used to indicate that the token type is a bitwise-or operator.
1908 */
1909 static final TokenClass BITWISE_OR_OPERATOR = new TokenClass.con2('BITWISE_OR_ OPERATOR', 4, 6);
1910
1911 /**
1912 * A value used to indicate that the token type is a bitwise-xor operator.
1913 */
1914 static final TokenClass BITWISE_XOR_OPERATOR = new TokenClass.con2('BITWISE_XO R_OPERATOR', 5, 7);
1915
1916 /**
1917 * A value used to indicate that the token type is a cascade operator.
1918 */
1919 static final TokenClass CASCADE_OPERATOR = new TokenClass.con2('CASCADE_OPERAT OR', 6, 2);
1920
1921 /**
1922 * A value used to indicate that the token type is a conditional operator.
1923 */
1924 static final TokenClass CONDITIONAL_OPERATOR = new TokenClass.con2('CONDITIONA L_OPERATOR', 7, 3);
1925
1926 /**
1927 * A value used to indicate that the token type is an equality operator.
1928 */
1929 static final TokenClass EQUALITY_OPERATOR = new TokenClass.con2('EQUALITY_OPER ATOR', 8, 9);
1930
1931 /**
1932 * A value used to indicate that the token type is a logical-and operator.
1933 */
1934 static final TokenClass LOGICAL_AND_OPERATOR = new TokenClass.con2('LOGICAL_AN D_OPERATOR', 9, 5);
1935
1936 /**
1937 * A value used to indicate that the token type is a logical-or operator.
1938 */
1939 static final TokenClass LOGICAL_OR_OPERATOR = new TokenClass.con2('LOGICAL_OR_ OPERATOR', 10, 4);
1940
1941 /**
1942 * A value used to indicate that the token type is a multiplicative operator.
1943 */
1944 static final TokenClass MULTIPLICATIVE_OPERATOR = new TokenClass.con2('MULTIPL ICATIVE_OPERATOR', 11, 13);
1945
1946 /**
1947 * A value used to indicate that the token type is a relational operator.
1948 */
1949 static final TokenClass RELATIONAL_OPERATOR = new TokenClass.con2('RELATIONAL_ OPERATOR', 12, 10);
1950
1951 /**
1952 * A value used to indicate that the token type is a shift operator.
1953 */
1954 static final TokenClass SHIFT_OPERATOR = new TokenClass.con2('SHIFT_OPERATOR', 13, 11);
1955
1956 /**
1957 * A value used to indicate that the token type is a unary operator.
1958 */
1959 static final TokenClass UNARY_POSTFIX_OPERATOR = new TokenClass.con2('UNARY_PO STFIX_OPERATOR', 14, 15);
1960
1961 /**
1962 * A value used to indicate that the token type is a unary operator.
1963 */
1964 static final TokenClass UNARY_PREFIX_OPERATOR = new TokenClass.con2('UNARY_PRE FIX_OPERATOR', 15, 14);
1965 static final List<TokenClass> values = [
1966 NO_CLASS,
1967 ADDITIVE_OPERATOR,
1968 ASSIGNMENT_OPERATOR,
1969 BITWISE_AND_OPERATOR,
1970 BITWISE_OR_OPERATOR,
1971 BITWISE_XOR_OPERATOR,
1972 CASCADE_OPERATOR,
1973 CONDITIONAL_OPERATOR,
1974 EQUALITY_OPERATOR,
1975 LOGICAL_AND_OPERATOR,
1976 LOGICAL_OR_OPERATOR,
1977 MULTIPLICATIVE_OPERATOR,
1978 RELATIONAL_OPERATOR,
1979 SHIFT_OPERATOR,
1980 UNARY_POSTFIX_OPERATOR,
1981 UNARY_PREFIX_OPERATOR];
1982
1983 /**
1984 * The precedence of tokens of this class, or `0` if the such tokens do not re present an
1985 * operator.
1986 */
1987 int precedence = 0;
1988 TokenClass.con1(String name, int ordinal) : this.con2(name, ordinal, 0);
1989 TokenClass.con2(String name, int ordinal, int precedence) : super(name, ordina l) {
1990 this.precedence = precedence;
1991 }
1992 }
1993 /**
1994 * Instances of the class `KeywordTokenWithComment` implement a keyword token th at is preceded
1995 * by comments.
1996 *
1997 * @coverage dart.engine.parser
1998 */
1999 class KeywordTokenWithComment extends KeywordToken {
2000
2001 /**
2002 * The first comment in the list of comments that precede this token.
2003 */
2004 Token _precedingComment;
2005
2006 /**
2007 * Initialize a newly created token to to represent the given keyword and to b e preceded by the
2008 * comments reachable from the given comment.
2009 *
2010 * @param keyword the keyword being represented by this token
2011 * @param offset the offset from the beginning of the file to the first charac ter in the token
2012 * @param precedingComment the first comment in the list of comments that prec ede this token
2013 */
2014 KeywordTokenWithComment(Keyword keyword, int offset, Token precedingComment) : super(keyword, offset) {
2015 this._precedingComment = precedingComment;
2016 }
2017 Token copy() => new KeywordTokenWithComment(keyword, offset, copyComments(_pre cedingComment));
2018 Token get precedingComments => _precedingComment;
2019 void applyDelta(int delta) {
2020 super.applyDelta(delta);
2021 Token token = _precedingComment;
2022 while (token != null) {
2023 token.applyDelta(delta);
2024 token = token.next;
2025 }
2026 }
2027 }
2028 /**
2029 * The enumeration `TokenType` defines the types of tokens that can be returned by the
2030 * scanner.
2031 *
2032 * @coverage dart.engine.parser
2033 */
2034 class TokenType extends Enum<TokenType> {
2035
2036 /**
2037 * The type of the token that marks the end of the input.
2038 */
2039 static final TokenType EOF = new TokenType_EOF('EOF', 0, null, "");
2040 static final TokenType DOUBLE = new TokenType.con1('DOUBLE', 1);
2041 static final TokenType HEXADECIMAL = new TokenType.con1('HEXADECIMAL', 2);
2042 static final TokenType IDENTIFIER = new TokenType.con1('IDENTIFIER', 3);
2043 static final TokenType INT = new TokenType.con1('INT', 4);
2044 static final TokenType KEYWORD = new TokenType.con1('KEYWORD', 5);
2045 static final TokenType MULTI_LINE_COMMENT = new TokenType.con1('MULTI_LINE_COM MENT', 6);
2046 static final TokenType SCRIPT_TAG = new TokenType.con1('SCRIPT_TAG', 7);
2047 static final TokenType SINGLE_LINE_COMMENT = new TokenType.con1('SINGLE_LINE_C OMMENT', 8);
2048 static final TokenType STRING = new TokenType.con1('STRING', 9);
2049 static final TokenType AMPERSAND = new TokenType.con2('AMPERSAND', 10, TokenCl ass.BITWISE_AND_OPERATOR, "&");
2050 static final TokenType AMPERSAND_AMPERSAND = new TokenType.con2('AMPERSAND_AMP ERSAND', 11, TokenClass.LOGICAL_AND_OPERATOR, "&&");
2051 static final TokenType AMPERSAND_EQ = new TokenType.con2('AMPERSAND_EQ', 12, T okenClass.ASSIGNMENT_OPERATOR, "&=");
2052 static final TokenType AT = new TokenType.con2('AT', 13, null, "@");
2053 static final TokenType BANG = new TokenType.con2('BANG', 14, TokenClass.UNARY_ PREFIX_OPERATOR, "!");
2054 static final TokenType BANG_EQ = new TokenType.con2('BANG_EQ', 15, TokenClass. EQUALITY_OPERATOR, "!=");
2055 static final TokenType BAR = new TokenType.con2('BAR', 16, TokenClass.BITWISE_ OR_OPERATOR, "|");
2056 static final TokenType BAR_BAR = new TokenType.con2('BAR_BAR', 17, TokenClass. LOGICAL_OR_OPERATOR, "||");
2057 static final TokenType BAR_EQ = new TokenType.con2('BAR_EQ', 18, TokenClass.AS SIGNMENT_OPERATOR, "|=");
2058 static final TokenType COLON = new TokenType.con2('COLON', 19, null, ":");
2059 static final TokenType COMMA = new TokenType.con2('COMMA', 20, null, ",");
2060 static final TokenType CARET = new TokenType.con2('CARET', 21, TokenClass.BITW ISE_XOR_OPERATOR, "^");
2061 static final TokenType CARET_EQ = new TokenType.con2('CARET_EQ', 22, TokenClas s.ASSIGNMENT_OPERATOR, "^=");
2062 static final TokenType CLOSE_CURLY_BRACKET = new TokenType.con2('CLOSE_CURLY_B RACKET', 23, null, "}");
2063 static final TokenType CLOSE_PAREN = new TokenType.con2('CLOSE_PAREN', 24, nul l, ")");
2064 static final TokenType CLOSE_SQUARE_BRACKET = new TokenType.con2('CLOSE_SQUARE _BRACKET', 25, null, "]");
2065 static final TokenType EQ = new TokenType.con2('EQ', 26, TokenClass.ASSIGNMENT _OPERATOR, "=");
2066 static final TokenType EQ_EQ = new TokenType.con2('EQ_EQ', 27, TokenClass.EQUA LITY_OPERATOR, "==");
2067 static final TokenType FUNCTION = new TokenType.con2('FUNCTION', 28, null, "=> ");
2068 static final TokenType GT = new TokenType.con2('GT', 29, TokenClass.RELATIONAL _OPERATOR, ">");
2069 static final TokenType GT_EQ = new TokenType.con2('GT_EQ', 30, TokenClass.RELA TIONAL_OPERATOR, ">=");
2070 static final TokenType GT_GT = new TokenType.con2('GT_GT', 31, TokenClass.SHIF T_OPERATOR, ">>");
2071 static final TokenType GT_GT_EQ = new TokenType.con2('GT_GT_EQ', 32, TokenClas s.ASSIGNMENT_OPERATOR, ">>=");
2072 static final TokenType HASH = new TokenType.con2('HASH', 33, null, "#");
2073 static final TokenType INDEX = new TokenType.con2('INDEX', 34, TokenClass.UNAR Y_POSTFIX_OPERATOR, "[]");
2074 static final TokenType INDEX_EQ = new TokenType.con2('INDEX_EQ', 35, TokenClas s.UNARY_POSTFIX_OPERATOR, "[]=");
2075 static final TokenType IS = new TokenType.con2('IS', 36, TokenClass.RELATIONAL _OPERATOR, "is");
2076 static final TokenType LT = new TokenType.con2('LT', 37, TokenClass.RELATIONAL _OPERATOR, "<");
2077 static final TokenType LT_EQ = new TokenType.con2('LT_EQ', 38, TokenClass.RELA TIONAL_OPERATOR, "<=");
2078 static final TokenType LT_LT = new TokenType.con2('LT_LT', 39, TokenClass.SHIF T_OPERATOR, "<<");
2079 static final TokenType LT_LT_EQ = new TokenType.con2('LT_LT_EQ', 40, TokenClas s.ASSIGNMENT_OPERATOR, "<<=");
2080 static final TokenType MINUS = new TokenType.con2('MINUS', 41, TokenClass.ADDI TIVE_OPERATOR, "-");
2081 static final TokenType MINUS_EQ = new TokenType.con2('MINUS_EQ', 42, TokenClas s.ASSIGNMENT_OPERATOR, "-=");
2082 static final TokenType MINUS_MINUS = new TokenType.con2('MINUS_MINUS', 43, Tok enClass.UNARY_PREFIX_OPERATOR, "--");
2083 static final TokenType OPEN_CURLY_BRACKET = new TokenType.con2('OPEN_CURLY_BRA CKET', 44, null, "{");
2084 static final TokenType OPEN_PAREN = new TokenType.con2('OPEN_PAREN', 45, Token Class.UNARY_POSTFIX_OPERATOR, "(");
2085 static final TokenType OPEN_SQUARE_BRACKET = new TokenType.con2('OPEN_SQUARE_B RACKET', 46, TokenClass.UNARY_POSTFIX_OPERATOR, "[");
2086 static final TokenType PERCENT = new TokenType.con2('PERCENT', 47, TokenClass. MULTIPLICATIVE_OPERATOR, "%");
2087 static final TokenType PERCENT_EQ = new TokenType.con2('PERCENT_EQ', 48, Token Class.ASSIGNMENT_OPERATOR, "%=");
2088 static final TokenType PERIOD = new TokenType.con2('PERIOD', 49, TokenClass.UN ARY_POSTFIX_OPERATOR, ".");
2089 static final TokenType PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD', 50, TokenClass.CASCADE_OPERATOR, "..");
2090 static final TokenType PLUS = new TokenType.con2('PLUS', 51, TokenClass.ADDITI VE_OPERATOR, "+");
2091 static final TokenType PLUS_EQ = new TokenType.con2('PLUS_EQ', 52, TokenClass. ASSIGNMENT_OPERATOR, "+=");
2092 static final TokenType PLUS_PLUS = new TokenType.con2('PLUS_PLUS', 53, TokenCl ass.UNARY_PREFIX_OPERATOR, "++");
2093 static final TokenType QUESTION = new TokenType.con2('QUESTION', 54, TokenClas s.CONDITIONAL_OPERATOR, "?");
2094 static final TokenType SEMICOLON = new TokenType.con2('SEMICOLON', 55, null, " ;");
2095 static final TokenType SLASH = new TokenType.con2('SLASH', 56, TokenClass.MULT IPLICATIVE_OPERATOR, "/");
2096 static final TokenType SLASH_EQ = new TokenType.con2('SLASH_EQ', 57, TokenClas s.ASSIGNMENT_OPERATOR, "/=");
2097 static final TokenType STAR = new TokenType.con2('STAR', 58, TokenClass.MULTIP LICATIVE_OPERATOR, "*");
2098 static final TokenType STAR_EQ = new TokenType.con2('STAR_EQ', 59, TokenClass. ASSIGNMENT_OPERATOR, "*=");
2099 static final TokenType STRING_INTERPOLATION_EXPRESSION = new TokenType.con2('S TRING_INTERPOLATION_EXPRESSION', 60, null, "\${");
2100 static final TokenType STRING_INTERPOLATION_IDENTIFIER = new TokenType.con2('S TRING_INTERPOLATION_IDENTIFIER', 61, null, "\$");
2101 static final TokenType TILDE = new TokenType.con2('TILDE', 62, TokenClass.UNAR Y_PREFIX_OPERATOR, "~");
2102 static final TokenType TILDE_SLASH = new TokenType.con2('TILDE_SLASH', 63, Tok enClass.MULTIPLICATIVE_OPERATOR, "~/");
2103 static final TokenType TILDE_SLASH_EQ = new TokenType.con2('TILDE_SLASH_EQ', 6 4, TokenClass.ASSIGNMENT_OPERATOR, "~/=");
2104 static final TokenType BACKPING = new TokenType.con2('BACKPING', 65, null, "`" );
2105 static final TokenType BACKSLASH = new TokenType.con2('BACKSLASH', 66, null, " \\");
2106 static final TokenType PERIOD_PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIO D_PERIOD', 67, null, "...");
2107 static final List<TokenType> values = [
2108 EOF,
2109 DOUBLE,
2110 HEXADECIMAL,
2111 IDENTIFIER,
2112 INT,
2113 KEYWORD,
2114 MULTI_LINE_COMMENT,
2115 SCRIPT_TAG,
2116 SINGLE_LINE_COMMENT,
2117 STRING,
2118 AMPERSAND,
2119 AMPERSAND_AMPERSAND,
2120 AMPERSAND_EQ,
2121 AT,
2122 BANG,
2123 BANG_EQ,
2124 BAR,
2125 BAR_BAR,
2126 BAR_EQ,
2127 COLON,
2128 COMMA,
2129 CARET,
2130 CARET_EQ,
2131 CLOSE_CURLY_BRACKET,
2132 CLOSE_PAREN,
2133 CLOSE_SQUARE_BRACKET,
2134 EQ,
2135 EQ_EQ,
2136 FUNCTION,
2137 GT,
2138 GT_EQ,
2139 GT_GT,
2140 GT_GT_EQ,
2141 HASH,
2142 INDEX,
2143 INDEX_EQ,
2144 IS,
2145 LT,
2146 LT_EQ,
2147 LT_LT,
2148 LT_LT_EQ,
2149 MINUS,
2150 MINUS_EQ,
2151 MINUS_MINUS,
2152 OPEN_CURLY_BRACKET,
2153 OPEN_PAREN,
2154 OPEN_SQUARE_BRACKET,
2155 PERCENT,
2156 PERCENT_EQ,
2157 PERIOD,
2158 PERIOD_PERIOD,
2159 PLUS,
2160 PLUS_EQ,
2161 PLUS_PLUS,
2162 QUESTION,
2163 SEMICOLON,
2164 SLASH,
2165 SLASH_EQ,
2166 STAR,
2167 STAR_EQ,
2168 STRING_INTERPOLATION_EXPRESSION,
2169 STRING_INTERPOLATION_IDENTIFIER,
2170 TILDE,
2171 TILDE_SLASH,
2172 TILDE_SLASH_EQ,
2173 BACKPING,
2174 BACKSLASH,
2175 PERIOD_PERIOD_PERIOD];
2176
2177 /**
2178 * The class of the token.
2179 */
2180 TokenClass _tokenClass;
2181
2182 /**
2183 * The lexeme that defines this type of token, or `null` if there is more than one possible
2184 * lexeme for this type of token.
2185 */
2186 String lexeme;
2187 TokenType.con1(String name, int ordinal) : this.con2(name, ordinal, TokenClass .NO_CLASS, null);
2188 TokenType.con2(String name, int ordinal, TokenClass tokenClass, String lexeme) : super(name, ordinal) {
2189 this._tokenClass = tokenClass == null ? TokenClass.NO_CLASS : tokenClass;
2190 this.lexeme = lexeme;
2191 }
2192
2193 /**
2194 * Return the precedence of the token, or `0` if the token does not represent an operator.
2195 *
2196 * @return the precedence of the token
2197 */
2198 int get precedence => _tokenClass.precedence;
2199
2200 /**
2201 * Return `true` if this type of token represents an additive operator.
2202 *
2203 * @return `true` if this type of token represents an additive operator
2204 */
2205 bool get isAdditiveOperator => identical(_tokenClass, TokenClass.ADDITIVE_OPER ATOR);
2206
2207 /**
2208 * Return `true` if this type of token represents an assignment operator.
2209 *
2210 * @return `true` if this type of token represents an assignment operator
2211 */
2212 bool get isAssignmentOperator => identical(_tokenClass, TokenClass.ASSIGNMENT_ OPERATOR);
2213
2214 /**
2215 * Return `true` if this type of token represents an associative operator. An associative
2216 * operator is an operator for which the following equality is true:
2217 * `(a * b) * c == a * (b * c)`. In other words, if the result of applying the operator to
2218 * multiple operands does not depend on the order in which those applications occur.
2219 *
2220 * Note: This method considers the logical-and and logical-or operators to be associative, even
2221 * though the order in which the application of those operators can have an ef fect because
2222 * evaluation of the right-hand operand is conditional.
2223 *
2224 * @return `true` if this type of token represents an associative operator
2225 */
2226 bool get isAssociativeOperator => identical(this, AMPERSAND) || identical(this , AMPERSAND_AMPERSAND) || identical(this, BAR) || identical(this, BAR_BAR) || id entical(this, CARET) || identical(this, PLUS) || identical(this, STAR);
2227
2228 /**
2229 * Return `true` if this type of token represents an equality operator.
2230 *
2231 * @return `true` if this type of token represents an equality operator
2232 */
2233 bool get isEqualityOperator => identical(_tokenClass, TokenClass.EQUALITY_OPER ATOR);
2234
2235 /**
2236 * Return `true` if this type of token represents an increment operator.
2237 *
2238 * @return `true` if this type of token represents an increment operator
2239 */
2240 bool get isIncrementOperator => identical(lexeme, "++") || identical(lexeme, " --");
2241
2242 /**
2243 * Return `true` if this type of token represents a multiplicative operator.
2244 *
2245 * @return `true` if this type of token represents a multiplicative operator
2246 */
2247 bool get isMultiplicativeOperator => identical(_tokenClass, TokenClass.MULTIPL ICATIVE_OPERATOR);
2248
2249 /**
2250 * Return `true` if this token type represents an operator.
2251 *
2252 * @return `true` if this token type represents an operator
2253 */
2254 bool get isOperator => _tokenClass != TokenClass.NO_CLASS && this != OPEN_PARE N && this != OPEN_SQUARE_BRACKET && this != PERIOD;
2255
2256 /**
2257 * Return `true` if this type of token represents a relational operator.
2258 *
2259 * @return `true` if this type of token represents a relational operator
2260 */
2261 bool get isRelationalOperator => identical(_tokenClass, TokenClass.RELATIONAL_ OPERATOR);
2262
2263 /**
2264 * Return `true` if this type of token represents a shift operator.
2265 *
2266 * @return `true` if this type of token represents a shift operator
2267 */
2268 bool get isShiftOperator => identical(_tokenClass, TokenClass.SHIFT_OPERATOR);
2269
2270 /**
2271 * Return `true` if this type of token represents a unary postfix operator.
2272 *
2273 * @return `true` if this type of token represents a unary postfix operator
2274 */
2275 bool get isUnaryPostfixOperator => identical(_tokenClass, TokenClass.UNARY_POS TFIX_OPERATOR);
2276
2277 /**
2278 * Return `true` if this type of token represents a unary prefix operator.
2279 *
2280 * @return `true` if this type of token represents a unary prefix operator
2281 */
2282 bool get isUnaryPrefixOperator => identical(_tokenClass, TokenClass.UNARY_PREF IX_OPERATOR);
2283
2284 /**
2285 * Return `true` if this token type represents an operator that can be defined by users.
2286 *
2287 * @return `true` if this token type represents an operator that can be define d by users
2288 */
2289 bool get isUserDefinableOperator => identical(lexeme, "==") || identical(lexem e, "~") || identical(lexeme, "[]") || identical(lexeme, "[]=") || identical(lexe me, "*") || identical(lexeme, "/") || identical(lexeme, "%") || identical(lexeme , "~/") || identical(lexeme, "+") || identical(lexeme, "-") || identical(lexeme, "<<") || identical(lexeme, ">>") || identical(lexeme, ">=") || identical(lexeme , ">") || identical(lexeme, "<=") || identical(lexeme, "<") || identical(lexeme, "&") || identical(lexeme, "^") || identical(lexeme, "|");
2290 }
2291 class TokenType_EOF extends TokenType {
2292 TokenType_EOF(String name, int ordinal, TokenClass arg0, String arg1) : super. con2(name, ordinal, arg0, arg1);
2293 String toString() => "-eof-";
2294 }
OLDNEW
« no previous file with comments | « pkg/analyzer_experimental/lib/src/generated/resolver.dart ('k') | pkg/analyzer_experimental/lib/src/generated/sdk.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698