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

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

Issue 12197019: Drop of generated scanner and example scanner driver. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 | 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
4 library engine.scanner;
5
6 import 'dart:collection';
7 import 'java_core.dart';
8 import 'source.dart';
9 import 'error.dart';
10 import 'instrumentation.dart';
11
12 /**
13 * The enumeration {@code Keyword} defines the keywords in the Dart programming language.
14 */
15 class Keyword {
16 static final Keyword ASSERT = new Keyword.con1('ASSERT', 0, "assert");
17 static final Keyword BREAK = new Keyword.con1('BREAK', 1, "break");
18 static final Keyword CASE = new Keyword.con1('CASE', 2, "case");
19 static final Keyword CATCH = new Keyword.con1('CATCH', 3, "catch");
20 static final Keyword CLASS = new Keyword.con1('CLASS', 4, "class");
21 static final Keyword CONST = new Keyword.con1('CONST', 5, "const");
22 static final Keyword CONTINUE = new Keyword.con1('CONTINUE', 6, "continue");
23 static final Keyword DEFAULT = new Keyword.con1('DEFAULT', 7, "default");
24 static final Keyword DO = new Keyword.con1('DO', 8, "do");
25 static final Keyword ELSE = new Keyword.con1('ELSE', 9, "else");
26 static final Keyword EXTENDS = new Keyword.con1('EXTENDS', 10, "extends");
27 static final Keyword FALSE = new Keyword.con1('FALSE', 11, "false");
28 static final Keyword FINAL = new Keyword.con1('FINAL', 12, "final");
29 static final Keyword FINALLY = new Keyword.con1('FINALLY', 13, "finally");
30 static final Keyword FOR = new Keyword.con1('FOR', 14, "for");
31 static final Keyword IF = new Keyword.con1('IF', 15, "if");
32 static final Keyword IN = new Keyword.con1('IN', 16, "in");
33 static final Keyword IS = new Keyword.con1('IS', 17, "is");
34 static final Keyword NEW = new Keyword.con1('NEW', 18, "new");
35 static final Keyword NULL = new Keyword.con1('NULL', 19, "null");
36 static final Keyword RETURN = new Keyword.con1('RETURN', 20, "return");
37 static final Keyword SUPER = new Keyword.con1('SUPER', 21, "super");
38 static final Keyword SWITCH = new Keyword.con1('SWITCH', 22, "switch");
39 static final Keyword THIS = new Keyword.con1('THIS', 23, "this");
40 static final Keyword THROW = new Keyword.con1('THROW', 24, "throw");
41 static final Keyword TRUE = new Keyword.con1('TRUE', 25, "true");
42 static final Keyword TRY = new Keyword.con1('TRY', 26, "try");
43 static final Keyword VAR = new Keyword.con1('VAR', 27, "var");
44 static final Keyword VOID = new Keyword.con1('VOID', 28, "void");
45 static final Keyword WHILE = new Keyword.con1('WHILE', 29, "while");
46 static final Keyword WITH = new Keyword.con1('WITH', 30, "with");
47 static final Keyword ABSTRACT = new Keyword.con2('ABSTRACT', 31, "abstract", t rue);
48 static final Keyword AS = new Keyword.con2('AS', 32, "as", true);
49 static final Keyword DYNAMIC = new Keyword.con2('DYNAMIC', 33, "dynamic", true );
50 static final Keyword EXPORT = new Keyword.con2('EXPORT', 34, "export", true);
51 static final Keyword EXTERNAL = new Keyword.con2('EXTERNAL', 35, "external", t rue);
52 static final Keyword FACTORY = new Keyword.con2('FACTORY', 36, "factory", true );
53 static final Keyword GET = new Keyword.con2('GET', 37, "get", true);
54 static final Keyword IMPLEMENTS = new Keyword.con2('IMPLEMENTS', 38, "implemen ts", true);
55 static final Keyword IMPORT = new Keyword.con2('IMPORT', 39, "import", true);
56 static final Keyword LIBRARY = new Keyword.con2('LIBRARY', 40, "library", true );
57 static final Keyword OPERATOR = new Keyword.con2('OPERATOR', 41, "operator", t rue);
58 static final Keyword PART = new Keyword.con2('PART', 42, "part", true);
59 static final Keyword SET = new Keyword.con2('SET', 43, "set", true);
60 static final Keyword STATIC = new Keyword.con2('STATIC', 44, "static", true);
61 static final Keyword TYPEDEF = new Keyword.con2('TYPEDEF', 45, "typedef", true );
62 static final List<Keyword> values = [ASSERT, BREAK, CASE, CATCH, CLASS, CONST, CONTINUE, DEFAULT, DO, ELSE, EXTENDS, FALSE, FINAL, FINALLY, FOR, IF, IN, IS, N EW, NULL, RETURN, SUPER, SWITCH, THIS, THROW, TRUE, TRY, VAR, VOID, WHILE, WITH, ABSTRACT, AS, DYNAMIC, EXPORT, EXTERNAL, FACTORY, GET, IMPLEMENTS, IMPORT, LIBR ARY, OPERATOR, PART, SET, STATIC, TYPEDEF];
63 String __name;
64 int __ordinal = 0;
65 /**
66 * The lexeme for the keyword.
67 */
68 String _syntax;
69 /**
70 * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords can be used as
71 * identifiers.
72 */
73 bool _isPseudoKeyword2 = false;
74 /**
75 * A table mapping the lexemes of keywords to the corresponding keyword.
76 */
77 static Map<String, Keyword> keywords = createKeywordMap();
78 /**
79 * Create a table mapping the lexemes of keywords to the corresponding keyword .
80 * @return the table that was created
81 */
82 static Map<String, Keyword> createKeywordMap() {
83 LinkedHashMap<String, Keyword> result = new LinkedHashMap<String, Keyword>() ;
84 for (Keyword keyword in values) {
85 result[keyword._syntax] = keyword;
86 }
87 return result;
88 }
89 /**
90 * Initialize a newly created keyword to have the given syntax. The keyword is not a
91 * pseudo-keyword.
92 * @param syntax the lexeme for the keyword
93 */
94 Keyword.con1(String ___name, int ___ordinal, String syntax) {
95 _jtd_constructor_215_impl(___name, ___ordinal, syntax);
96 }
97 _jtd_constructor_215_impl(String ___name, int ___ordinal, String syntax) {
98 _jtd_constructor_216_impl(___name, ___ordinal, syntax, false);
99 }
100 /**
101 * Initialize a newly created keyword to have the given syntax. The keyword is a pseudo-keyword if
102 * the given flag is {@code true}.
103 * @param syntax the lexeme for the keyword
104 * @param isPseudoKeyword {@code true} if this keyword is a pseudo-keyword
105 */
106 Keyword.con2(String ___name, int ___ordinal, String syntax, bool isPseudoKeywo rd) {
107 _jtd_constructor_216_impl(___name, ___ordinal, syntax, isPseudoKeyword);
108 }
109 _jtd_constructor_216_impl(String ___name, int ___ordinal, String syntax, bool isPseudoKeyword) {
110 __name = ___name;
111 __ordinal = ___ordinal;
112 this._syntax = syntax;
113 this._isPseudoKeyword2 = isPseudoKeyword;
114 }
115 /**
116 * Return the lexeme for the keyword.
117 * @return the lexeme for the keyword
118 */
119 String get syntax => _syntax;
120 /**
121 * Return {@code true} if this keyword is a pseudo-keyword. Pseudo keywords ca n be used as
122 * identifiers.
123 * @return {@code true} if this keyword is a pseudo-keyword
124 */
125 bool isPseudoKeyword() => _isPseudoKeyword2;
126 String toString() => __name;
127 }
128 /**
129 * Instances of the class {@code CharBufferScanner} implement a scanner that rea ds from a character
130 * buffer. The scanning logic is in the superclass.
131 */
132 class CharBufferScanner extends AbstractScanner {
133 /**
134 * The buffer from which characters will be read.
135 */
136 CharBuffer _buffer;
137 /**
138 * The number of characters in the buffer.
139 */
140 int _bufferLength = 0;
141 /**
142 * The index of the last character that was read.
143 */
144 int _charOffset = 0;
145 /**
146 * Initialize a newly created scanner to scan the characters in the given char acter buffer.
147 * @param source the source being scanned
148 * @param buffer the buffer from which characters will be read
149 * @param errorListener the error listener that will be informed of any errors that are found
150 */
151 CharBufferScanner(Source source, CharBuffer buffer, AnalysisErrorListener erro rListener) : super(source, errorListener) {
152 this._buffer = buffer;
153 this._bufferLength = buffer.length();
154 this._charOffset = -1;
155 }
156 int get offset => _charOffset;
157 int advance() {
158 if (_charOffset + 1 >= _bufferLength) {
159 return -1;
160 }
161 return _buffer.charAt(++_charOffset);
162 }
163 String getString(int start, int endDelta) => _buffer.subSequence(start, _charO ffset + 1 + endDelta).toString();
164 int peek() {
165 if (_charOffset + 1 >= _buffer.length()) {
166 return -1;
167 }
168 return _buffer.charAt(_charOffset + 1);
169 }
170 }
171 /**
172 * Instances of the class {@code TokenWithComment} represent a normal token that is preceded by
173 * comments.
174 */
175 class TokenWithComment extends Token {
176 /**
177 * The first comment in the list of comments that precede this token.
178 */
179 Token _precedingComment;
180 /**
181 * Initialize a newly created token to have the given type and offset and to b e preceded by the
182 * comments reachable from the given comment.
183 * @param type the type of the token
184 * @param offset the offset from the beginning of the file to the first charac ter in the token
185 * @param precedingComment the first comment in the list of comments that prec ede this token
186 */
187 TokenWithComment(TokenType type, int offset, Token precedingComment) : super(t ype, offset) {
188 this._precedingComment = precedingComment;
189 }
190 Token get precedingComments => _precedingComment;
191 }
192 /**
193 * Instances of the class {@code Token} represent a token that was scanned from the input. Each
194 * token knows which token follows it, acting as the head of a linked list of to kens.
195 */
196 class Token {
197 /**
198 * The type of the token.
199 */
200 TokenType _type;
201 /**
202 * The offset from the beginning of the file to the first character in the tok en.
203 */
204 int _offset = 0;
205 /**
206 * The previous token in the token stream.
207 */
208 Token _previous;
209 /**
210 * The next token in the token stream.
211 */
212 Token _next;
213 /**
214 * Initialize a newly created token to have the given type and offset.
215 * @param type the type of the token
216 * @param offset the offset from the beginning of the file to the first charac ter in the token
217 */
218 Token(TokenType type, int offset) {
219 this._type = type;
220 this._offset = offset;
221 }
222 /**
223 * Return the offset from the beginning of the file to the character after las t character of the
224 * token.
225 * @return the offset from the beginning of the file to the first character af ter last character
226 * of the token
227 */
228 int get end => _offset + length;
229 /**
230 * Return the number of characters in the node's source range.
231 * @return the number of characters in the node's source range
232 */
233 int get length => lexeme.length;
234 /**
235 * Return the lexeme that represents this token.
236 * @return the lexeme that represents this token
237 */
238 String get lexeme => _type.lexeme;
239 /**
240 * Return the next token in the token stream.
241 * @return the next token in the token stream
242 */
243 Token get next => _next;
244 /**
245 * Return the offset from the beginning of the file to the first character in the token.
246 * @return the offset from the beginning of the file to the first character in the token
247 */
248 int get offset => _offset;
249 /**
250 * Return the first comment in the list of comments that precede this token, o r {@code null} if
251 * there are no comments preceding this token. Additional comments can be reac hed by following the
252 * token stream using {@link #getNext()} until {@code null} is returned.
253 * @return the first comment in the list of comments that precede this token
254 */
255 Token get precedingComments => null;
256 /**
257 * Return the previous token in the token stream.
258 * @return the previous token in the token stream
259 */
260 Token get previous => _previous;
261 /**
262 * Return the type of the token.
263 * @return the type of the token
264 */
265 TokenType get type => _type;
266 /**
267 * Return {@code true} if this token represents an operator.
268 * @return {@code true} if this token represents an operator
269 */
270 bool isOperator() => _type.isOperator();
271 /**
272 * Return {@code true} if this token is a synthetic token. A synthetic token i s a token that was
273 * introduced by the parser in order to recover from an error in the code. Syn thetic tokens always
274 * have a length of zero ({@code 0}).
275 * @return {@code true} if this token is a synthetic token
276 */
277 bool isSynthetic() => length == 0;
278 /**
279 * Return {@code true} if this token represents an operator that can be define d by users.
280 * @return {@code true} if this token represents an operator that can be defin ed by users
281 */
282 bool isUserDefinableOperator() => _type.isUserDefinableOperator();
283 /**
284 * Set the next token in the token stream to the given token. This has the sid e-effect of setting
285 * this token to be the previous token for the given token.
286 * @param token the next token in the token stream
287 * @return the token that was passed in
288 */
289 Token setNext(Token token) {
290 _next = token;
291 token.previous2 = this;
292 return token;
293 }
294 /**
295 * Set the next token in the token stream to the given token without changing which token is the
296 * previous token for the given token.
297 * @param token the next token in the token stream
298 * @return the token that was passed in
299 */
300 Token setNextWithoutSettingPrevious(Token token) {
301 _next = token;
302 return token;
303 }
304 /**
305 * Set the offset from the beginning of the file to the first character in the token to the given
306 * offset.
307 * @param offset the offset from the beginning of the file to the first charac ter in the token
308 */
309 void set offset2(int offset) {
310 this._offset = offset;
311 }
312 String toString() => lexeme;
313 /**
314 * Return the value of this token. For keyword tokens, this is the keyword ass ociated with the
315 * token, for other tokens it is the lexeme associated with the token.
316 * @return the value of this token
317 */
318 Object value() => _type.lexeme;
319 /**
320 * Set the previous token in the token stream to the given token.
321 * @param previous the previous token in the token stream
322 */
323 void set previous2(Token previous) {
324 this._previous = previous;
325 }
326 }
327 /**
328 * Instances of the class {@code KeywordToken} represent a keyword in the langua ge.
329 */
330 class KeywordToken extends Token {
331 /**
332 * The keyword being represented by this token.
333 */
334 Keyword _keyword;
335 /**
336 * Initialize a newly created token to represent the given keyword.
337 * @param keyword the keyword being represented by this token
338 * @param offset the offset from the beginning of the file to the first charac ter in the token
339 */
340 KeywordToken(Keyword keyword, int offset) : super(TokenType.KEYWORD, offset) {
341 this._keyword = keyword;
342 }
343 /**
344 * Return the keyword being represented by this token.
345 * @return the keyword being represented by this token
346 */
347 Keyword get keyword => _keyword;
348 String get lexeme => _keyword.syntax;
349 Keyword value() => _keyword;
350 }
351 /**
352 * Instances of the class {@code StringToken} represent a token whose value is i ndependent of it's
353 * type.
354 */
355 class StringToken extends Token {
356 /**
357 * The lexeme represented by this token.
358 */
359 String _value2;
360 /**
361 * Initialize a newly created token to represent a token of the given type wit h the given value.
362 * @param type the type of the token
363 * @param value the lexeme represented by this token
364 * @param offset the offset from the beginning of the file to the first charac ter in the token
365 */
366 StringToken(TokenType type, String value, int offset) : super(type, offset) {
367 this._value2 = value;
368 }
369 String get lexeme => _value2;
370 String value() => _value2;
371 }
372 /**
373 * The enumeration {@code ScannerErrorCode} defines the error codes used for err ors detected by the
374 * scanner.
375 */
376 class ScannerErrorCode implements ErrorCode {
377 static final ScannerErrorCode ILLEGAL_CHARACTER = new ScannerErrorCode('ILLEGA L_CHARACTER', 0, "Illegal character %x");
378 static final ScannerErrorCode MISSING_DIGIT = new ScannerErrorCode('MISSING_DI GIT', 1, "Decimal digit expected");
379 static final ScannerErrorCode MISSING_HEX_DIGIT = new ScannerErrorCode('MISSIN G_HEX_DIGIT', 2, "Hexidecimal digit expected");
380 static final ScannerErrorCode MISSING_QUOTE = new ScannerErrorCode('MISSING_QU OTE', 3, "Expected quote (' or \")");
381 static final ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT = new ScannerErr orCode('UNTERMINATED_MULTI_LINE_COMMENT', 4, "Unterminated multi-line comment");
382 static final ScannerErrorCode UNTERMINATED_STRING_LITERAL = new ScannerErrorCo de('UNTERMINATED_STRING_LITERAL', 5, "Unterminated string literal");
383 static final List<ScannerErrorCode> values = [ILLEGAL_CHARACTER, MISSING_DIGIT , MISSING_HEX_DIGIT, MISSING_QUOTE, UNTERMINATED_MULTI_LINE_COMMENT, UNTERMINATE D_STRING_LITERAL];
384 final String __name;
385 final int __ordinal;
386 /**
387 * The message template used to create the message to be displayed for this er ror.
388 */
389 String _message;
390 /**
391 * Initialize a newly created error code to have the given message.
392 * @param message the message template used to create the message to be displa yed for this error
393 */
394 ScannerErrorCode(this.__name, this.__ordinal, String message) {
395 this._message = message;
396 }
397 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
398 String get message => _message;
399 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
400 bool needsRecompilation() => true;
401 String toString() => __name;
402 }
403 /**
404 * Instances of the class {@code BeginTokenWithComment} represent a begin token that is preceded by
405 * comments.
406 */
407 class BeginTokenWithComment extends BeginToken {
408 /**
409 * The first comment in the list of comments that precede this token.
410 */
411 Token _precedingComment;
412 /**
413 * Initialize a newly created token to have the given type and offset and to b e preceded by the
414 * comments reachable from the given comment.
415 * @param type the type of the token
416 * @param offset the offset from the beginning of the file to the first charac ter in the token
417 * @param precedingComment the first comment in the list of comments that prec ede this token
418 */
419 BeginTokenWithComment(TokenType type, int offset, Token precedingComment) : su per(type, offset) {
420 this._precedingComment = precedingComment;
421 }
422 Token get precedingComments => _precedingComment;
423 }
424 /**
425 * The enumeration {@code TokenType} defines the types of tokens that can be ret urned by the
426 * scanner.
427 */
428 class TokenType {
429 /**
430 * The type of the token that marks the end of the input.
431 */
432 static final TokenType EOF = new TokenType_EOF('EOF', 0, null, "");
433 static final TokenType DOUBLE = new TokenType.con1('DOUBLE', 1);
434 static final TokenType HEXADECIMAL = new TokenType.con1('HEXADECIMAL', 2);
435 static final TokenType IDENTIFIER = new TokenType.con1('IDENTIFIER', 3);
436 static final TokenType INT = new TokenType.con1('INT', 4);
437 static final TokenType KEYWORD = new TokenType.con1('KEYWORD', 5);
438 static final TokenType MULTI_LINE_COMMENT = new TokenType.con1('MULTI_LINE_COM MENT', 6);
439 static final TokenType SCRIPT_TAG = new TokenType.con1('SCRIPT_TAG', 7);
440 static final TokenType SINGLE_LINE_COMMENT = new TokenType.con1('SINGLE_LINE_C OMMENT', 8);
441 static final TokenType STRING = new TokenType.con1('STRING', 9);
442 static final TokenType AMPERSAND = new TokenType.con2('AMPERSAND', 10, TokenCl ass.BITWISE_AND_OPERATOR, "&");
443 static final TokenType AMPERSAND_AMPERSAND = new TokenType.con2('AMPERSAND_AMP ERSAND', 11, TokenClass.LOGICAL_AND_OPERATOR, "&&");
444 static final TokenType AMPERSAND_EQ = new TokenType.con2('AMPERSAND_EQ', 12, T okenClass.ASSIGNMENT_OPERATOR, "&=");
445 static final TokenType AT = new TokenType.con2('AT', 13, null, "@");
446 static final TokenType BANG = new TokenType.con2('BANG', 14, TokenClass.UNARY_ PREFIX_OPERATOR, "!");
447 static final TokenType BANG_EQ = new TokenType.con2('BANG_EQ', 15, TokenClass. EQUALITY_OPERATOR, "!=");
448 static final TokenType BAR = new TokenType.con2('BAR', 16, TokenClass.BITWISE_ OR_OPERATOR, "|");
449 static final TokenType BAR_BAR = new TokenType.con2('BAR_BAR', 17, TokenClass. LOGICAL_OR_OPERATOR, "||");
450 static final TokenType BAR_EQ = new TokenType.con2('BAR_EQ', 18, TokenClass.AS SIGNMENT_OPERATOR, "|=");
451 static final TokenType COLON = new TokenType.con2('COLON', 19, null, ":");
452 static final TokenType COMMA = new TokenType.con2('COMMA', 20, null, ",");
453 static final TokenType CARET = new TokenType.con2('CARET', 21, TokenClass.BITW ISE_XOR_OPERATOR, "^");
454 static final TokenType CARET_EQ = new TokenType.con2('CARET_EQ', 22, TokenClas s.ASSIGNMENT_OPERATOR, "^=");
455 static final TokenType CLOSE_CURLY_BRACKET = new TokenType.con2('CLOSE_CURLY_B RACKET', 23, null, "}");
456 static final TokenType CLOSE_PAREN = new TokenType.con2('CLOSE_PAREN', 24, nul l, ")");
457 static final TokenType CLOSE_SQUARE_BRACKET = new TokenType.con2('CLOSE_SQUARE _BRACKET', 25, null, "]");
458 static final TokenType EQ = new TokenType.con2('EQ', 26, TokenClass.ASSIGNMENT _OPERATOR, "=");
459 static final TokenType EQ_EQ = new TokenType.con2('EQ_EQ', 27, TokenClass.EQUA LITY_OPERATOR, "==");
460 static final TokenType FUNCTION = new TokenType.con2('FUNCTION', 28, null, "=> ");
461 static final TokenType GT = new TokenType.con2('GT', 29, TokenClass.RELATIONAL _OPERATOR, ">");
462 static final TokenType GT_EQ = new TokenType.con2('GT_EQ', 30, TokenClass.RELA TIONAL_OPERATOR, ">=");
463 static final TokenType GT_GT = new TokenType.con2('GT_GT', 31, TokenClass.SHIF T_OPERATOR, ">>");
464 static final TokenType GT_GT_EQ = new TokenType.con2('GT_GT_EQ', 32, TokenClas s.ASSIGNMENT_OPERATOR, ">>=");
465 static final TokenType HASH = new TokenType.con2('HASH', 33, null, "#");
466 static final TokenType INDEX = new TokenType.con2('INDEX', 34, TokenClass.UNAR Y_POSTFIX_OPERATOR, "[]");
467 static final TokenType INDEX_EQ = new TokenType.con2('INDEX_EQ', 35, TokenClas s.UNARY_POSTFIX_OPERATOR, "[]=");
468 static final TokenType IS = new TokenType.con2('IS', 36, TokenClass.RELATIONAL _OPERATOR, "is");
469 static final TokenType LT = new TokenType.con2('LT', 37, TokenClass.RELATIONAL _OPERATOR, "<");
470 static final TokenType LT_EQ = new TokenType.con2('LT_EQ', 38, TokenClass.RELA TIONAL_OPERATOR, "<=");
471 static final TokenType LT_LT = new TokenType.con2('LT_LT', 39, TokenClass.SHIF T_OPERATOR, "<<");
472 static final TokenType LT_LT_EQ = new TokenType.con2('LT_LT_EQ', 40, TokenClas s.ASSIGNMENT_OPERATOR, "<<=");
473 static final TokenType MINUS = new TokenType.con2('MINUS', 41, TokenClass.ADDI TIVE_OPERATOR, "-");
474 static final TokenType MINUS_EQ = new TokenType.con2('MINUS_EQ', 42, TokenClas s.ASSIGNMENT_OPERATOR, "-=");
475 static final TokenType MINUS_MINUS = new TokenType.con2('MINUS_MINUS', 43, Tok enClass.UNARY_PREFIX_OPERATOR, "--");
476 static final TokenType OPEN_CURLY_BRACKET = new TokenType.con2('OPEN_CURLY_BRA CKET', 44, null, "{");
477 static final TokenType OPEN_PAREN = new TokenType.con2('OPEN_PAREN', 45, Token Class.UNARY_POSTFIX_OPERATOR, "(");
478 static final TokenType OPEN_SQUARE_BRACKET = new TokenType.con2('OPEN_SQUARE_B RACKET', 46, TokenClass.UNARY_POSTFIX_OPERATOR, "[");
479 static final TokenType PERCENT = new TokenType.con2('PERCENT', 47, TokenClass. MULTIPLICATIVE_OPERATOR, "%");
480 static final TokenType PERCENT_EQ = new TokenType.con2('PERCENT_EQ', 48, Token Class.ASSIGNMENT_OPERATOR, "%=");
481 static final TokenType PERIOD = new TokenType.con2('PERIOD', 49, TokenClass.UN ARY_POSTFIX_OPERATOR, ".");
482 static final TokenType PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD', 50, TokenClass.CASCADE_OPERATOR, "..");
483 static final TokenType PLUS = new TokenType.con2('PLUS', 51, TokenClass.ADDITI VE_OPERATOR, "+");
484 static final TokenType PLUS_EQ = new TokenType.con2('PLUS_EQ', 52, TokenClass. ASSIGNMENT_OPERATOR, "+=");
485 static final TokenType PLUS_PLUS = new TokenType.con2('PLUS_PLUS', 53, TokenCl ass.UNARY_PREFIX_OPERATOR, "++");
486 static final TokenType QUESTION = new TokenType.con2('QUESTION', 54, TokenClas s.CONDITIONAL_OPERATOR, "?");
487 static final TokenType SEMICOLON = new TokenType.con2('SEMICOLON', 55, null, " ;");
488 static final TokenType SLASH = new TokenType.con2('SLASH', 56, TokenClass.MULT IPLICATIVE_OPERATOR, "/");
489 static final TokenType SLASH_EQ = new TokenType.con2('SLASH_EQ', 57, TokenClas s.ASSIGNMENT_OPERATOR, "/=");
490 static final TokenType STAR = new TokenType.con2('STAR', 58, TokenClass.MULTIP LICATIVE_OPERATOR, "*");
491 static final TokenType STAR_EQ = new TokenType.con2('STAR_EQ', 59, TokenClass. ASSIGNMENT_OPERATOR, "*=");
492 static final TokenType STRING_INTERPOLATION_EXPRESSION = new TokenType.con2('S TRING_INTERPOLATION_EXPRESSION', 60, null, "\${");
493 static final TokenType STRING_INTERPOLATION_IDENTIFIER = new TokenType.con2('S TRING_INTERPOLATION_IDENTIFIER', 61, null, "\$");
494 static final TokenType TILDE = new TokenType.con2('TILDE', 62, TokenClass.UNAR Y_PREFIX_OPERATOR, "~");
495 static final TokenType TILDE_SLASH = new TokenType.con2('TILDE_SLASH', 63, Tok enClass.MULTIPLICATIVE_OPERATOR, "~/");
496 static final TokenType TILDE_SLASH_EQ = new TokenType.con2('TILDE_SLASH_EQ', 6 4, TokenClass.ASSIGNMENT_OPERATOR, "~/=");
497 static final TokenType BACKPING = new TokenType.con2('BACKPING', 65, null, "`" );
498 static final TokenType BACKSLASH = new TokenType.con2('BACKSLASH', 66, null, " \\");
499 static final TokenType PERIOD_PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIO D_PERIOD', 67, null, "...");
500 static final List<TokenType> values = [EOF, DOUBLE, HEXADECIMAL, IDENTIFIER, I NT, KEYWORD, MULTI_LINE_COMMENT, SCRIPT_TAG, SINGLE_LINE_COMMENT, STRING, AMPERS AND, AMPERSAND_AMPERSAND, AMPERSAND_EQ, AT, BANG, BANG_EQ, BAR, BAR_BAR, BAR_EQ, COLON, COMMA, CARET, CARET_EQ, CLOSE_CURLY_BRACKET, CLOSE_PAREN, CLOSE_SQUARE_B RACKET, EQ, EQ_EQ, FUNCTION, GT, GT_EQ, GT_GT, GT_GT_EQ, HASH, INDEX, INDEX_EQ, IS, LT, LT_EQ, LT_LT, LT_LT_EQ, MINUS, MINUS_EQ, MINUS_MINUS, OPEN_CURLY_BRACKET , OPEN_PAREN, OPEN_SQUARE_BRACKET, PERCENT, PERCENT_EQ, PERIOD, PERIOD_PERIOD, P LUS, PLUS_EQ, PLUS_PLUS, QUESTION, SEMICOLON, SLASH, SLASH_EQ, STAR, STAR_EQ, ST RING_INTERPOLATION_EXPRESSION, STRING_INTERPOLATION_IDENTIFIER, TILDE, TILDE_SLA SH, TILDE_SLASH_EQ, BACKPING, BACKSLASH, PERIOD_PERIOD_PERIOD];
501 String __name;
502 int __ordinal = 0;
503 /**
504 * The class of the token.
505 */
506 TokenClass _tokenClass;
507 /**
508 * The lexeme that defines this type of token, or {@code null} if there is mor e than one possible
509 * lexeme for this type of token.
510 */
511 String _lexeme;
512 TokenType.con1(String ___name, int ___ordinal) {
513 _jtd_constructor_227_impl(___name, ___ordinal);
514 }
515 _jtd_constructor_227_impl(String ___name, int ___ordinal) {
516 _jtd_constructor_228_impl(___name, ___ordinal, TokenClass.NO_CLASS, null);
517 }
518 TokenType.con2(String ___name, int ___ordinal, TokenClass tokenClass, String l exeme) {
519 _jtd_constructor_228_impl(___name, ___ordinal, tokenClass, lexeme);
520 }
521 _jtd_constructor_228_impl(String ___name, int ___ordinal, TokenClass tokenClas s, String lexeme) {
522 __name = ___name;
523 __ordinal = ___ordinal;
524 this._tokenClass = tokenClass == null ? TokenClass.NO_CLASS : tokenClass;
525 this._lexeme = lexeme;
526 }
527 /**
528 * Return the lexeme that defines this type of token, or {@code null} if there is more than one
529 * possible lexeme for this type of token.
530 * @return the lexeme that defines this type of token
531 */
532 String get lexeme => _lexeme;
533 /**
534 * Return the precedence of the token, or {@code 0} if the token does not repr esent an operator.
535 * @return the precedence of the token
536 */
537 int get precedence => _tokenClass.precedence;
538 /**
539 * Return {@code true} if this type of token represents an additive operator.
540 * @return {@code true} if this type of token represents an additive operator
541 */
542 bool isAdditiveOperator() => _tokenClass == TokenClass.ADDITIVE_OPERATOR;
543 /**
544 * Return {@code true} if this type of token represents an assignment operator .
545 * @return {@code true} if this type of token represents an assignment operato r
546 */
547 bool isAssignmentOperator() => _tokenClass == TokenClass.ASSIGNMENT_OPERATOR;
548 /**
549 * Return {@code true} if this type of token represents an equality operator.
550 * @return {@code true} if this type of token represents an equality operator
551 */
552 bool isEqualityOperator() => _tokenClass == TokenClass.EQUALITY_OPERATOR;
553 /**
554 * Return {@code true} if this type of token represents an increment operator.
555 * @return {@code true} if this type of token represents an increment operator
556 */
557 bool isIncrementOperator() => _lexeme == "++" || _lexeme == "--";
558 /**
559 * Return {@code true} if this type of token represents a multiplicative opera tor.
560 * @return {@code true} if this type of token represents a multiplicative oper ator
561 */
562 bool isMultiplicativeOperator() => _tokenClass == TokenClass.MULTIPLICATIVE_OP ERATOR;
563 /**
564 * Return {@code true} if this token type represents an operator.
565 * @return {@code true} if this token type represents an operator
566 */
567 bool isOperator() => _tokenClass != TokenClass.NO_CLASS && this != TokenType.O PEN_PAREN && this != TokenType.OPEN_SQUARE_BRACKET && this != TokenType.PERIOD;
568 /**
569 * Return {@code true} if this type of token represents a relational operator.
570 * @return {@code true} if this type of token represents a relational operator
571 */
572 bool isRelationalOperator() => _tokenClass == TokenClass.RELATIONAL_OPERATOR;
573 /**
574 * Return {@code true} if this type of token represents a shift operator.
575 * @return {@code true} if this type of token represents a shift operator
576 */
577 bool isShiftOperator() => _tokenClass == TokenClass.SHIFT_OPERATOR;
578 /**
579 * Return {@code true} if this type of token represents a unary postfix operat or.
580 * @return {@code true} if this type of token represents a unary postfix opera tor
581 */
582 bool isUnaryPostfixOperator() => _tokenClass == TokenClass.UNARY_POSTFIX_OPERA TOR;
583 /**
584 * Return {@code true} if this type of token represents a unary prefix operato r.
585 * @return {@code true} if this type of token represents a unary prefix operat or
586 */
587 bool isUnaryPrefixOperator() => _tokenClass == TokenClass.UNARY_PREFIX_OPERATO R;
588 /**
589 * Return {@code true} if this token type represents an operator that can be d efined by users.
590 * @return {@code true} if this token type represents an operator that can be defined by users
591 */
592 bool isUserDefinableOperator() => _lexeme == "==" || _lexeme == "~" || _lexeme == "[]" || _lexeme == "[]=" || _lexeme == "*" || _lexeme == "/" || _lexeme == " %" || _lexeme == "~/" || _lexeme == "+" || _lexeme == "-" || _lexeme == "<<" || _lexeme == ">>" || _lexeme == ">=" || _lexeme == ">" || _lexeme == "<=" || _lexe me == "<" || _lexeme == "&" || _lexeme == "^" || _lexeme == "|";
593 String toString() => __name;
594 }
595 class TokenType_EOF extends TokenType {
596 TokenType_EOF(String ___name, int ___ordinal, TokenClass arg0, String arg1) : super.con2(___name, ___ordinal, arg0, arg1);
597 String toString() => "-eof-";
598 }
599 /**
600 * Instances of the class {@code TokenWithComment} represent a string token that is preceded by
601 * comments.
602 */
603 class StringTokenWithComment extends StringToken {
604 /**
605 * The first comment in the list of comments that precede this token.
606 */
607 Token _precedingComment;
608 /**
609 * Initialize a newly created token to have the given type and offset and to b e preceded by the
610 * comments reachable from the given comment.
611 * @param type the type of the token
612 * @param offset the offset from the beginning of the file to the first charac ter in the token
613 * @param precedingComment the first comment in the list of comments that prec ede this token
614 */
615 StringTokenWithComment(TokenType type, String value, int offset, Token precedi ngComment) : super(type, value, offset) {
616 this._precedingComment = precedingComment;
617 }
618 Token get precedingComments => _precedingComment;
619 }
620 /**
621 * Instances of the class {@code BeginToken} represent the opening half of a gro uping pair of
622 * tokens. This is used for curly brackets ('{'), parentheses ('('), and square brackets ('[').
623 */
624 class BeginToken extends Token {
625 /**
626 * The token that corresponds to this token.
627 */
628 Token _endToken;
629 /**
630 * Initialize a newly created token representing the opening half of a groupin g pair of tokens.
631 * @param type the type of the token
632 * @param offset the offset from the beginning of the file to the first charac ter in the token
633 */
634 BeginToken(TokenType type, int offset) : super(type, offset) {
635 assert((type == TokenType.OPEN_CURLY_BRACKET || type == TokenType.OPEN_PAREN || type == TokenType.OPEN_SQUARE_BRACKET || type == TokenType.STRING_INTERPOLAT ION_EXPRESSION));
636 }
637 /**
638 * Return the token that corresponds to this token.
639 * @return the token that corresponds to this token
640 */
641 Token get endToken => _endToken;
642 /**
643 * Set the token that corresponds to this token to the given token.
644 * @param token the token that corresponds to this token
645 */
646 void set endToken2(Token token) {
647 this._endToken = token;
648 }
649 }
650 /**
651 * The enumeration {@code TokenClass} represents classes (or groups) of tokens w ith a similar use.
652 */
653 class TokenClass {
654 /**
655 * A value used to indicate that the token type is not part of any specific cl ass of token.
656 */
657 static final TokenClass NO_CLASS = new TokenClass.con1('NO_CLASS', 0);
658 /**
659 * A value used to indicate that the token type is an additive operator.
660 */
661 static final TokenClass ADDITIVE_OPERATOR = new TokenClass.con2('ADDITIVE_OPER ATOR', 1, 12);
662 /**
663 * A value used to indicate that the token type is an assignment operator.
664 */
665 static final TokenClass ASSIGNMENT_OPERATOR = new TokenClass.con2('ASSIGNMENT_ OPERATOR', 2, 1);
666 /**
667 * A value used to indicate that the token type is a bitwise-and operator.
668 */
669 static final TokenClass BITWISE_AND_OPERATOR = new TokenClass.con2('BITWISE_AN D_OPERATOR', 3, 8);
670 /**
671 * A value used to indicate that the token type is a bitwise-or operator.
672 */
673 static final TokenClass BITWISE_OR_OPERATOR = new TokenClass.con2('BITWISE_OR_ OPERATOR', 4, 6);
674 /**
675 * A value used to indicate that the token type is a bitwise-xor operator.
676 */
677 static final TokenClass BITWISE_XOR_OPERATOR = new TokenClass.con2('BITWISE_XO R_OPERATOR', 5, 7);
678 /**
679 * A value used to indicate that the token type is a cascade operator.
680 */
681 static final TokenClass CASCADE_OPERATOR = new TokenClass.con2('CASCADE_OPERAT OR', 6, 2);
682 /**
683 * A value used to indicate that the token type is a conditional operator.
684 */
685 static final TokenClass CONDITIONAL_OPERATOR = new TokenClass.con2('CONDITIONA L_OPERATOR', 7, 3);
686 /**
687 * A value used to indicate that the token type is an equality operator.
688 */
689 static final TokenClass EQUALITY_OPERATOR = new TokenClass.con2('EQUALITY_OPER ATOR', 8, 9);
690 /**
691 * A value used to indicate that the token type is a logical-and operator.
692 */
693 static final TokenClass LOGICAL_AND_OPERATOR = new TokenClass.con2('LOGICAL_AN D_OPERATOR', 9, 5);
694 /**
695 * A value used to indicate that the token type is a logical-or operator.
696 */
697 static final TokenClass LOGICAL_OR_OPERATOR = new TokenClass.con2('LOGICAL_OR_ OPERATOR', 10, 4);
698 /**
699 * A value used to indicate that the token type is a multiplicative operator.
700 */
701 static final TokenClass MULTIPLICATIVE_OPERATOR = new TokenClass.con2('MULTIPL ICATIVE_OPERATOR', 11, 13);
702 /**
703 * A value used to indicate that the token type is a relational operator.
704 */
705 static final TokenClass RELATIONAL_OPERATOR = new TokenClass.con2('RELATIONAL_ OPERATOR', 12, 10);
706 /**
707 * A value used to indicate that the token type is a shift operator.
708 */
709 static final TokenClass SHIFT_OPERATOR = new TokenClass.con2('SHIFT_OPERATOR', 13, 11);
710 /**
711 * A value used to indicate that the token type is a unary operator.
712 */
713 static final TokenClass UNARY_POSTFIX_OPERATOR = new TokenClass.con2('UNARY_PO STFIX_OPERATOR', 14, 15);
714 /**
715 * A value used to indicate that the token type is a unary operator.
716 */
717 static final TokenClass UNARY_PREFIX_OPERATOR = new TokenClass.con2('UNARY_PRE FIX_OPERATOR', 15, 14);
718 static final List<TokenClass> values = [NO_CLASS, ADDITIVE_OPERATOR, ASSIGNMEN T_OPERATOR, BITWISE_AND_OPERATOR, BITWISE_OR_OPERATOR, BITWISE_XOR_OPERATOR, CAS CADE_OPERATOR, CONDITIONAL_OPERATOR, EQUALITY_OPERATOR, LOGICAL_AND_OPERATOR, LO GICAL_OR_OPERATOR, MULTIPLICATIVE_OPERATOR, RELATIONAL_OPERATOR, SHIFT_OPERATOR, UNARY_POSTFIX_OPERATOR, UNARY_PREFIX_OPERATOR];
719 String __name;
720 int __ordinal = 0;
721 /**
722 * The precedence of tokens of this class, or {@code 0} if the such tokens do not represent an
723 * operator.
724 */
725 int _precedence = 0;
726 TokenClass.con1(String ___name, int ___ordinal) {
727 _jtd_constructor_225_impl(___name, ___ordinal);
728 }
729 _jtd_constructor_225_impl(String ___name, int ___ordinal) {
730 _jtd_constructor_226_impl(___name, ___ordinal, 0);
731 }
732 TokenClass.con2(String ___name, int ___ordinal, int precedence) {
733 _jtd_constructor_226_impl(___name, ___ordinal, precedence);
734 }
735 _jtd_constructor_226_impl(String ___name, int ___ordinal, int precedence) {
736 __name = ___name;
737 __ordinal = ___ordinal;
738 this._precedence = precedence;
739 }
740 /**
741 * Return the precedence of tokens of this class, or {@code 0} if the such tok ens do not represent
742 * an operator.
743 * @return the precedence of tokens of this class
744 */
745 int get precedence => _precedence;
746 String toString() => __name;
747 }
748 /**
749 * Instances of the class {@code StringScanner} implement a scanner that reads f rom a string. The
750 * scanning logic is in the superclass.
751 */
752 class StringScanner extends AbstractScanner {
753 /**
754 * The offset from the beginning of the file to the beginning of the source be ing scanned.
755 */
756 int _offsetDelta = 0;
757 /**
758 * The string from which characters will be read.
759 */
760 String _string;
761 /**
762 * The number of characters in the string.
763 */
764 int _stringLength = 0;
765 /**
766 * The index, relative to the string, of the last character that was read.
767 */
768 int _charOffset = 0;
769 /**
770 * Initialize a newly created scanner to scan the characters in the given stri ng.
771 * @param source the source being scanned
772 * @param string the string from which characters will be read
773 * @param errorListener the error listener that will be informed of any errors that are found
774 */
775 StringScanner(Source source, String string, AnalysisErrorListener errorListene r) : super(source, errorListener) {
776 this._offsetDelta = 0;
777 this._string = string;
778 this._stringLength = string.length;
779 this._charOffset = -1;
780 }
781 int get offset => _offsetDelta + _charOffset;
782 /**
783 * Record that the source begins on the given line and column at the given off set. The line starts
784 * for lines before the given line will not be correct.
785 * <p>
786 * This method must be invoked at most one time and must be invoked before sca nning begins. The
787 * values provided must be sensible. The results are undefined if these condit ions are violated.
788 * @param line the one-based index of the line containing the first character of the source
789 * @param column the one-based index of the column in which the first characte r of the source
790 * occurs
791 * @param offset the zero-based offset from the beginning of the larger contex t to the first
792 * character of the source
793 */
794 void setSourceStart(int line, int column, int offset) {
795 if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
796 return;
797 }
798 _offsetDelta = 1;
799 for (int i = 2; i < line; i++) {
800 recordStartOfLine();
801 }
802 _offsetDelta = offset - column + 1;
803 recordStartOfLine();
804 _offsetDelta = offset;
805 }
806 int advance() {
807 if (_charOffset + 1 >= _stringLength) {
808 return -1;
809 }
810 return _string.charCodeAt(++_charOffset);
811 }
812 String getString(int start, int endDelta) => _string.substring(start - _offset Delta, _charOffset + 1 + endDelta);
813 int peek() {
814 if (_charOffset + 1 >= _string.length) {
815 return -1;
816 }
817 return _string.charCodeAt(_charOffset + 1);
818 }
819 }
820 /**
821 * The abstract class {@code AbstractScanner} implements a scanner for Dart code . Subclasses are
822 * required to implement the interface used to access the characters being scann ed.
823 * <p>
824 * The lexical structure of Dart is ambiguous without knowledge of the context i n which a token is
825 * being scanned. For example, without context we cannot determine whether sourc e of the form "<<"
826 * should be scanned as a single left-shift operator or as two left angle bracke ts. This scanner
827 * does not have any context, so it always resolves such conflicts by scanning t he longest possible
828 * token.
829 */
830 abstract class AbstractScanner {
831 /**
832 * The source being scanned.
833 */
834 Source _source;
835 /**
836 * The error listener that will be informed of any errors that are found durin g the scan.
837 */
838 AnalysisErrorListener _errorListener;
839 /**
840 * The token pointing to the head of the linked list of tokens.
841 */
842 Token _tokens;
843 /**
844 * The last token that was scanned.
845 */
846 Token _tail;
847 /**
848 * The first token in the list of comment tokens found since the last non-comm ent token.
849 */
850 Token _firstComment;
851 /**
852 * The last token in the list of comment tokens found since the last non-comme nt token.
853 */
854 Token _lastComment;
855 /**
856 * The index of the first character of the current token.
857 */
858 int _tokenStart = 0;
859 /**
860 * A list containing the offsets of the first character of each line in the so urce code.
861 */
862 List<int> _lineStarts = new List<int>();
863 /**
864 * A list, treated something like a stack, of tokens representing the beginnin g of a matched pair.
865 * It is used to pair the end tokens with the begin tokens.
866 */
867 List<BeginToken> _groupingStack = new List<BeginToken>();
868 /**
869 * A flag indicating whether any unmatched groups were found during the parse.
870 */
871 bool _hasUnmatchedGroups2 = false;
872 /**
873 * A non-breaking space, which is allowed by this scanner as a white-space cha racter.
874 */
875 static int _$NBSP = 160;
876 /**
877 * Initialize a newly created scanner.
878 * @param source the source being scanned
879 * @param errorListener the error listener that will be informed of any errors that are found
880 */
881 AbstractScanner(Source source, AnalysisErrorListener errorListener) {
882 this._source = source;
883 this._errorListener = errorListener;
884 _tokens = new Token(TokenType.EOF, -1);
885 _tokens.setNext(_tokens);
886 _tail = _tokens;
887 _tokenStart = -1;
888 _lineStarts.add(0);
889 }
890 /**
891 * Return an array containing the offsets of the first character of each line in the source code.
892 * @return an array containing the offsets of the first character of each line in the source code
893 */
894 List<int> get lineStarts => _lineStarts;
895 /**
896 * Return the current offset relative to the beginning of the file. Return the initial offset if
897 * the scanner has not yet scanned the source code, and one (1) past the end o f the source code if
898 * the source code has been scanned.
899 * @return the current offset of the scanner in the source
900 */
901 int get offset;
902 /**
903 * Return {@code true} if any unmatched groups were found during the parse.
904 * @return {@code true} if any unmatched groups were found during the parse
905 */
906 bool hasUnmatchedGroups() => _hasUnmatchedGroups2;
907 /**
908 * Scan the source code to produce a list of tokens representing the source.
909 * @return the first token in the list of tokens that were produced
910 */
911 Token tokenize() {
912 int startTime = System.currentTimeMillis();
913 int next = advance();
914 while (next != -1) {
915 next = bigSwitch(next);
916 }
917 appendEofToken();
918 int endTime = System.currentTimeMillis();
919 Instrumentation.metric2("Engine-Scanner", endTime - startTime).with3("chars" , offset).log();
920 return firstToken();
921 }
922 /**
923 * Advance the current position and return the character at the new current po sition.
924 * @return the character at the new current position
925 */
926 int advance();
927 /**
928 * Return the substring of the source code between the start offset and the mo dified current
929 * position. The current position is modified by adding the end delta.
930 * @param start the offset to the beginning of the string, relative to the sta rt of the file
931 * @param endDelta the number of character after the current location to be in cluded in the
932 * string, or the number of characters before the current location to be exclu ded if the
933 * offset is negative
934 * @return the specified substring of the source code
935 */
936 String getString(int start, int endDelta);
937 /**
938 * Return the character at the current position without changing the current p osition.
939 * @return the character at the current position
940 */
941 int peek();
942 /**
943 * Record the fact that we are at the beginning of a new line in the source.
944 */
945 void recordStartOfLine() {
946 _lineStarts.add(offset);
947 }
948 void appendBeginToken(TokenType type) {
949 BeginToken token;
950 if (_firstComment == null) {
951 token = new BeginToken(type, _tokenStart);
952 } else {
953 token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
954 _firstComment = null;
955 _lastComment = null;
956 }
957 _tail = _tail.setNext(token);
958 _groupingStack.add(token);
959 }
960 void appendCommentToken(TokenType type, String value) {
961 if (_firstComment == null) {
962 _firstComment = new StringToken(type, value, _tokenStart);
963 _lastComment = _firstComment;
964 } else {
965 _lastComment = _lastComment.setNext(new StringToken(type, value, _tokenSta rt));
966 }
967 }
968 void appendEndToken(TokenType type, TokenType beginType) {
969 Token token;
970 if (_firstComment == null) {
971 token = new Token(type, _tokenStart);
972 } else {
973 token = new TokenWithComment(type, _tokenStart, _firstComment);
974 _firstComment = null;
975 _lastComment = null;
976 }
977 _tail = _tail.setNext(token);
978 int last = _groupingStack.length - 1;
979 if (last >= 0) {
980 BeginToken begin = _groupingStack[last];
981 if (begin.type == beginType) {
982 begin.endToken2 = token;
983 _groupingStack.removeAt(last);
984 }
985 }
986 }
987 void appendEofToken() {
988 Token eofToken;
989 if (_firstComment == null) {
990 eofToken = new Token(TokenType.EOF, offset + 1);
991 } else {
992 eofToken = new TokenWithComment(TokenType.EOF, offset + 1, _firstComment);
993 _firstComment = null;
994 _lastComment = null;
995 }
996 eofToken.setNext(eofToken);
997 _tail = _tail.setNext(eofToken);
998 if (!_groupingStack.isEmpty) {
999 _hasUnmatchedGroups2 = true;
1000 }
1001 }
1002 void appendKeywordToken(Keyword keyword) {
1003 if (_firstComment == null) {
1004 _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
1005 } else {
1006 _tail = _tail.setNext(new KeywordTokenWithComment(keyword, _tokenStart, _f irstComment));
1007 _firstComment = null;
1008 _lastComment = null;
1009 }
1010 }
1011 void appendStringToken(TokenType type, String value) {
1012 if (_firstComment == null) {
1013 _tail = _tail.setNext(new StringToken(type, value, _tokenStart));
1014 } else {
1015 _tail = _tail.setNext(new StringTokenWithComment(type, value, _tokenStart, _firstComment));
1016 _firstComment = null;
1017 _lastComment = null;
1018 }
1019 }
1020 void appendStringToken2(TokenType type, String value, int offset) {
1021 if (_firstComment == null) {
1022 _tail = _tail.setNext(new StringToken(type, value, _tokenStart + offset));
1023 } else {
1024 _tail = _tail.setNext(new StringTokenWithComment(type, value, _tokenStart + offset, _firstComment));
1025 _firstComment = null;
1026 _lastComment = null;
1027 }
1028 }
1029 void appendToken(TokenType type) {
1030 if (_firstComment == null) {
1031 _tail = _tail.setNext(new Token(type, _tokenStart));
1032 } else {
1033 _tail = _tail.setNext(new TokenWithComment(type, _tokenStart, _firstCommen t));
1034 _firstComment = null;
1035 _lastComment = null;
1036 }
1037 }
1038 void appendToken2(TokenType type, int offset) {
1039 if (_firstComment == null) {
1040 _tail = _tail.setNext(new Token(type, offset));
1041 } else {
1042 _tail = _tail.setNext(new TokenWithComment(type, offset, _firstComment));
1043 _firstComment = null;
1044 _lastComment = null;
1045 }
1046 }
1047 void beginToken() {
1048 _tokenStart = offset;
1049 }
1050 int bigSwitch(int next) {
1051 beginToken();
1052 if (next == 0xd) {
1053 next = advance();
1054 if (next == 0xa) {
1055 next = advance();
1056 }
1057 recordStartOfLine();
1058 return next;
1059 } else if (next == 0xa) {
1060 recordStartOfLine();
1061 return advance();
1062 } else if (next == 0x9 || next == 0x20) {
1063 return advance();
1064 }
1065 if (next == 0x72) {
1066 int peek3 = peek();
1067 if (peek3 == 0x22 || peek3 == 0x27) {
1068 int start = offset;
1069 return tokenizeString(advance(), start, true);
1070 }
1071 }
1072 if (0x61 <= next && next <= 0x7a) {
1073 return tokenizeKeywordOrIdentifier(next, true);
1074 }
1075 if ((0x41 <= next && next <= 0x5a) || next == 0x5f || next == 0x24) {
1076 return tokenizeIdentifier(next, offset, true);
1077 }
1078 if (next == 0x3c) {
1079 return tokenizeLessThan(next);
1080 }
1081 if (next == 0x3e) {
1082 return tokenizeGreaterThan(next);
1083 }
1084 if (next == 0x3d) {
1085 return tokenizeEquals(next);
1086 }
1087 if (next == 0x21) {
1088 return tokenizeExclamation(next);
1089 }
1090 if (next == 0x2b) {
1091 return tokenizePlus(next);
1092 }
1093 if (next == 0x2d) {
1094 return tokenizeMinus(next);
1095 }
1096 if (next == 0x2a) {
1097 return tokenizeMultiply(next);
1098 }
1099 if (next == 0x25) {
1100 return tokenizePercent(next);
1101 }
1102 if (next == 0x26) {
1103 return tokenizeAmpersand(next);
1104 }
1105 if (next == 0x7c) {
1106 return tokenizeBar(next);
1107 }
1108 if (next == 0x5e) {
1109 return tokenizeCaret(next);
1110 }
1111 if (next == 0x5b) {
1112 return tokenizeOpenSquareBracket(next);
1113 }
1114 if (next == 0x7e) {
1115 return tokenizeTilde(next);
1116 }
1117 if (next == 0x5c) {
1118 appendToken(TokenType.BACKSLASH);
1119 return advance();
1120 }
1121 if (next == 0x23) {
1122 return tokenizeTag(next);
1123 }
1124 if (next == 0x28) {
1125 appendBeginToken(TokenType.OPEN_PAREN);
1126 return advance();
1127 }
1128 if (next == 0x29) {
1129 appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
1130 return advance();
1131 }
1132 if (next == 0x2c) {
1133 appendToken(TokenType.COMMA);
1134 return advance();
1135 }
1136 if (next == 0x3a) {
1137 appendToken(TokenType.COLON);
1138 return advance();
1139 }
1140 if (next == 0x3b) {
1141 appendToken(TokenType.SEMICOLON);
1142 return advance();
1143 }
1144 if (next == 0x3f) {
1145 appendToken(TokenType.QUESTION);
1146 return advance();
1147 }
1148 if (next == 0x5d) {
1149 appendEndToken(TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACK ET);
1150 return advance();
1151 }
1152 if (next == 0x60) {
1153 appendToken(TokenType.BACKPING);
1154 return advance();
1155 }
1156 if (next == 0x7b) {
1157 appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
1158 return advance();
1159 }
1160 if (next == 0x7d) {
1161 appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET );
1162 return advance();
1163 }
1164 if (next == 0x2f) {
1165 return tokenizeSlashOrComment(next);
1166 }
1167 if (next == 0x40) {
1168 appendToken(TokenType.AT);
1169 return advance();
1170 }
1171 if (next == 0x22 || next == 0x27) {
1172 return tokenizeString(next, offset, false);
1173 }
1174 if (next == 0x2e) {
1175 return tokenizeDotOrNumber(next);
1176 }
1177 if (next == 0x30) {
1178 return tokenizeHexOrNumber(next);
1179 }
1180 if (0x31 <= next && next <= 0x39) {
1181 return tokenizeNumber(next);
1182 }
1183 if (next == -1) {
1184 return -1;
1185 }
1186 if (Character.isLetter(next)) {
1187 return tokenizeIdentifier(next, offset, true);
1188 }
1189 if (next == AbstractScanner._$NBSP) {
1190 return advance();
1191 }
1192 reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
1193 return advance();
1194 }
1195 /**
1196 * Return the beginning token corresponding to a closing brace that was found while scanning
1197 * inside a string interpolation expression. Tokens that cannot be matched wit h the closing brace
1198 * will be dropped from the stack.
1199 * @return the token to be paired with the closing brace
1200 */
1201 BeginToken findTokenMatchingClosingBraceInInterpolationExpression() {
1202 int last = _groupingStack.length - 1;
1203 while (last >= 0) {
1204 BeginToken begin = _groupingStack[last];
1205 if (begin.type == TokenType.OPEN_CURLY_BRACKET || begin.type == TokenType. STRING_INTERPOLATION_EXPRESSION) {
1206 return begin;
1207 }
1208 _hasUnmatchedGroups2 = true;
1209 _groupingStack.removeAt(last);
1210 last--;
1211 }
1212 return null;
1213 }
1214 Token firstToken() => _tokens.next;
1215 /**
1216 * Return the source being scanned.
1217 * @return the source being scanned
1218 */
1219 Source get source => _source;
1220 /**
1221 * Report an error at the current offset.
1222 * @param errorCode the error code indicating the nature of the error
1223 * @param arguments any arguments needed to complete the error message
1224 */
1225 void reportError(ScannerErrorCode errorCode, List<Object> arguments) {
1226 _errorListener.onError(new AnalysisError.con2(source, offset, 1, errorCode, [arguments]));
1227 }
1228 int select(int choice, TokenType yesType, TokenType noType) {
1229 int next = advance();
1230 if (next == choice) {
1231 appendToken(yesType);
1232 return advance();
1233 } else {
1234 appendToken(noType);
1235 return next;
1236 }
1237 }
1238 int select2(int choice, TokenType yesType, TokenType noType, int offset) {
1239 int next = advance();
1240 if (next == choice) {
1241 appendToken2(yesType, offset);
1242 return advance();
1243 } else {
1244 appendToken2(noType, offset);
1245 return next;
1246 }
1247 }
1248 int tokenizeAmpersand(int next) {
1249 next = advance();
1250 if (next == 0x26) {
1251 appendToken(TokenType.AMPERSAND_AMPERSAND);
1252 return advance();
1253 } else if (next == 0x3d) {
1254 appendToken(TokenType.AMPERSAND_EQ);
1255 return advance();
1256 } else {
1257 appendToken(TokenType.AMPERSAND);
1258 return next;
1259 }
1260 }
1261 int tokenizeBar(int next) {
1262 next = advance();
1263 if (next == 0x7c) {
1264 appendToken(TokenType.BAR_BAR);
1265 return advance();
1266 } else if (next == 0x3d) {
1267 appendToken(TokenType.BAR_EQ);
1268 return advance();
1269 } else {
1270 appendToken(TokenType.BAR);
1271 return next;
1272 }
1273 }
1274 int tokenizeCaret(int next) => select(0x3d, TokenType.CARET_EQ, TokenType.CARE T);
1275 int tokenizeDotOrNumber(int next) {
1276 int start = offset;
1277 next = advance();
1278 if ((0x30 <= next && next <= 0x39)) {
1279 return tokenizeFractionPart(next, start);
1280 } else if (0x2e == next) {
1281 return select(0x2e, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIO D);
1282 } else {
1283 appendToken(TokenType.PERIOD);
1284 return next;
1285 }
1286 }
1287 int tokenizeEquals(int next) {
1288 next = advance();
1289 if (next == 0x3d) {
1290 appendToken(TokenType.EQ_EQ);
1291 return advance();
1292 } else if (next == 0x3e) {
1293 appendToken(TokenType.FUNCTION);
1294 return advance();
1295 }
1296 appendToken(TokenType.EQ);
1297 return next;
1298 }
1299 int tokenizeExclamation(int next) {
1300 next = advance();
1301 if (next == 0x3d) {
1302 appendToken(TokenType.BANG_EQ);
1303 return advance();
1304 }
1305 appendToken(TokenType.BANG);
1306 return next;
1307 }
1308 int tokenizeExponent(int next) {
1309 if (next == 0x2b || next == 0x2d) {
1310 next = advance();
1311 }
1312 bool hasDigits = false;
1313 while (true) {
1314 if (0x30 <= next && next <= 0x39) {
1315 hasDigits = true;
1316 } else {
1317 if (!hasDigits) {
1318 reportError(ScannerErrorCode.MISSING_DIGIT, []);
1319 }
1320 return next;
1321 }
1322 next = advance();
1323 }
1324 }
1325 int tokenizeFractionPart(int next, int start) {
1326 bool done = false;
1327 bool hasDigit = false;
1328 LOOP: while (!done) {
1329 if (0x30 <= next && next <= 0x39) {
1330 hasDigit = true;
1331 } else if (0x65 == next || 0x45 == next) {
1332 hasDigit = true;
1333 next = tokenizeExponent(advance());
1334 done = true;
1335 continue LOOP;
1336 } else {
1337 done = true;
1338 continue LOOP;
1339 }
1340 next = advance();
1341 }
1342 if (!hasDigit) {
1343 appendStringToken(TokenType.INT, getString(start, -2));
1344 if (0x2e == next) {
1345 return select2(0x2e, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PE RIOD, offset - 1);
1346 }
1347 appendToken2(TokenType.PERIOD, offset - 1);
1348 return bigSwitch(next);
1349 }
1350 if (next == 0x64 || next == 0x44) {
1351 next = advance();
1352 }
1353 appendStringToken(TokenType.DOUBLE, getString(start, next < 0 ? 0 : -1));
1354 return next;
1355 }
1356 int tokenizeGreaterThan(int next) {
1357 next = advance();
1358 if (0x3d == next) {
1359 appendToken(TokenType.GT_EQ);
1360 return advance();
1361 } else if (0x3e == next) {
1362 next = advance();
1363 if (0x3d == next) {
1364 appendToken(TokenType.GT_GT_EQ);
1365 return advance();
1366 } else {
1367 appendToken(TokenType.GT_GT);
1368 return next;
1369 }
1370 } else {
1371 appendToken(TokenType.GT);
1372 return next;
1373 }
1374 }
1375 int tokenizeHex(int next) {
1376 int start = offset - 1;
1377 bool hasDigits = false;
1378 while (true) {
1379 next = advance();
1380 if ((0x30 <= next && next <= 0x39) || (0x41 <= next && next <= 0x46) || (0 x61 <= next && next <= 0x66)) {
1381 hasDigits = true;
1382 } else {
1383 if (!hasDigits) {
1384 reportError(ScannerErrorCode.MISSING_HEX_DIGIT, []);
1385 }
1386 appendStringToken(TokenType.HEXADECIMAL, getString(start, next < 0 ? 0 : -1));
1387 return next;
1388 }
1389 }
1390 }
1391 int tokenizeHexOrNumber(int next) {
1392 int x = peek();
1393 if (x == 0x78 || x == 0x58) {
1394 advance();
1395 return tokenizeHex(x);
1396 }
1397 return tokenizeNumber(next);
1398 }
1399 int tokenizeIdentifier(int next, int start, bool allowDollar) {
1400 while ((0x61 <= next && next <= 0x7a) || (0x41 <= next && next <= 0x5a) || ( 0x30 <= next && next <= 0x39) || next == 0x5f || (next == 0x24 && allowDollar) | | Character.isLetterOrDigit(next)) {
1401 next = advance();
1402 }
1403 appendStringToken(TokenType.IDENTIFIER, getString(start, next < 0 ? 0 : -1)) ;
1404 return next;
1405 }
1406 int tokenizeInterpolatedExpression(int next, int start) {
1407 appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
1408 next = advance();
1409 while (next != -1) {
1410 if (next == 0x7d) {
1411 BeginToken begin = findTokenMatchingClosingBraceInInterpolationExpressio n();
1412 if (begin == null) {
1413 beginToken();
1414 appendToken(TokenType.CLOSE_CURLY_BRACKET);
1415 next = advance();
1416 beginToken();
1417 return next;
1418 } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) {
1419 beginToken();
1420 appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRA CKET);
1421 next = advance();
1422 beginToken();
1423 } else if (begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
1424 beginToken();
1425 appendEndToken(TokenType.CLOSE_CURLY_BRACKET, TokenType.STRING_INTERPO LATION_EXPRESSION);
1426 next = advance();
1427 beginToken();
1428 return next;
1429 }
1430 } else {
1431 next = bigSwitch(next);
1432 }
1433 }
1434 if (next == -1) {
1435 return next;
1436 }
1437 next = advance();
1438 beginToken();
1439 return next;
1440 }
1441 int tokenizeInterpolatedIdentifier(int next, int start) {
1442 appendStringToken2(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
1443 beginToken();
1444 next = tokenizeKeywordOrIdentifier(next, false);
1445 beginToken();
1446 return next;
1447 }
1448 int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
1449 KeywordState state = KeywordState.KEYWORD_STATE;
1450 int start = offset;
1451 while (state != null && 0x61 <= next && next <= 0x7a) {
1452 state = state.next(next as int);
1453 next = advance();
1454 }
1455 if (state == null || state.keyword() == null) {
1456 return tokenizeIdentifier(next, start, allowDollar);
1457 }
1458 if ((0x41 <= next && next <= 0x5a) || (0x30 <= next && next <= 0x39) || next == 0x5f || next == 0x24) {
1459 return tokenizeIdentifier(next, start, allowDollar);
1460 } else if (next < 128) {
1461 appendKeywordToken(state.keyword());
1462 return next;
1463 } else {
1464 return tokenizeIdentifier(next, start, allowDollar);
1465 }
1466 }
1467 int tokenizeLessThan(int next) {
1468 next = advance();
1469 if (0x3d == next) {
1470 appendToken(TokenType.LT_EQ);
1471 return advance();
1472 } else if (0x3c == next) {
1473 return select(0x3d, TokenType.LT_LT_EQ, TokenType.LT_LT);
1474 } else {
1475 appendToken(TokenType.LT);
1476 return next;
1477 }
1478 }
1479 int tokenizeMinus(int next) {
1480 next = advance();
1481 if (next == 0x2d) {
1482 appendToken(TokenType.MINUS_MINUS);
1483 return advance();
1484 } else if (next == 0x3d) {
1485 appendToken(TokenType.MINUS_EQ);
1486 return advance();
1487 } else {
1488 appendToken(TokenType.MINUS);
1489 return next;
1490 }
1491 }
1492 int tokenizeMultiLineComment(int next) {
1493 int nesting = 1;
1494 next = advance();
1495 while (true) {
1496 if (-1 == next) {
1497 reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, []);
1498 appendCommentToken(TokenType.MULTI_LINE_COMMENT, getString(_tokenStart, 0));
1499 return next;
1500 } else if (0x2a == next) {
1501 next = advance();
1502 if (0x2f == next) {
1503 --nesting;
1504 if (0 == nesting) {
1505 appendCommentToken(TokenType.MULTI_LINE_COMMENT, getString(_tokenSta rt, 0));
1506 return advance();
1507 } else {
1508 next = advance();
1509 }
1510 }
1511 } else if (0x2f == next) {
1512 next = advance();
1513 if (0x2a == next) {
1514 next = advance();
1515 ++nesting;
1516 }
1517 } else {
1518 next = advance();
1519 }
1520 }
1521 }
1522 int tokenizeMultiLineRawString(int quoteChar, int start) {
1523 int next = advance();
1524 outer: while (next != -1) {
1525 while (next != quoteChar) {
1526 next = advance();
1527 if (next == -1) {
1528 break outer;
1529 }
1530 }
1531 next = advance();
1532 if (next == quoteChar) {
1533 next = advance();
1534 if (next == quoteChar) {
1535 appendStringToken(TokenType.STRING, getString(start, 0));
1536 return advance();
1537 }
1538 }
1539 }
1540 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1541 appendStringToken(TokenType.STRING, getString(start, 0));
1542 return advance();
1543 }
1544 int tokenizeMultiLineString(int quoteChar, int start, bool raw) {
1545 if (raw) {
1546 return tokenizeMultiLineRawString(quoteChar, start);
1547 }
1548 int next = advance();
1549 while (next != -1) {
1550 if (next == 0x24) {
1551 appendStringToken(TokenType.STRING, getString(start, -1));
1552 beginToken();
1553 next = tokenizeStringInterpolation(start);
1554 start = offset;
1555 continue;
1556 }
1557 if (next == quoteChar) {
1558 next = advance();
1559 if (next == quoteChar) {
1560 next = advance();
1561 if (next == quoteChar) {
1562 appendStringToken(TokenType.STRING, getString(start, 0));
1563 return advance();
1564 }
1565 }
1566 continue;
1567 }
1568 if (next == 0x5c) {
1569 next = advance();
1570 if (next == -1) {
1571 break;
1572 }
1573 }
1574 next = advance();
1575 }
1576 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1577 appendStringToken(TokenType.STRING, getString(start, 0));
1578 return advance();
1579 }
1580 int tokenizeMultiply(int next) => select(0x3d, TokenType.STAR_EQ, TokenType.ST AR);
1581 int tokenizeNumber(int next) {
1582 int start = offset;
1583 while (true) {
1584 next = advance();
1585 if (0x30 <= next && next <= 0x39) {
1586 continue;
1587 } else if (next == 0x2e) {
1588 return tokenizeFractionPart(advance(), start);
1589 } else if (next == 0x64 || next == 0x44) {
1590 appendStringToken(TokenType.DOUBLE, getString(start, 0));
1591 return advance();
1592 } else if (next == 0x65 || next == 0x45) {
1593 return tokenizeFractionPart(next, start);
1594 } else {
1595 appendStringToken(TokenType.INT, getString(start, next < 0 ? 0 : -1));
1596 return next;
1597 }
1598 }
1599 }
1600 int tokenizeOpenSquareBracket(int next) {
1601 next = advance();
1602 if (next == 0x5d) {
1603 return select(0x3d, TokenType.INDEX_EQ, TokenType.INDEX);
1604 } else {
1605 appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
1606 return next;
1607 }
1608 }
1609 int tokenizePercent(int next) => select(0x3d, TokenType.PERCENT_EQ, TokenType. PERCENT);
1610 int tokenizePlus(int next) {
1611 next = advance();
1612 if (0x2b == next) {
1613 appendToken(TokenType.PLUS_PLUS);
1614 return advance();
1615 } else if (0x3d == next) {
1616 appendToken(TokenType.PLUS_EQ);
1617 return advance();
1618 } else {
1619 appendToken(TokenType.PLUS);
1620 return next;
1621 }
1622 }
1623 int tokenizeSingleLineComment(int next) {
1624 while (true) {
1625 next = advance();
1626 if (0xa == next || 0xd == next || -1 == next) {
1627 appendCommentToken(TokenType.SINGLE_LINE_COMMENT, getString(_tokenStart, 0));
1628 return next;
1629 }
1630 }
1631 }
1632 int tokenizeSingleLineRawString(int next, int quoteChar, int start) {
1633 next = advance();
1634 while (next != -1) {
1635 if (next == quoteChar) {
1636 appendStringToken(TokenType.STRING, getString(start, 0));
1637 return advance();
1638 } else if (next == 0xd || next == 0xa) {
1639 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1640 appendStringToken(TokenType.STRING, getString(start, 0));
1641 return advance();
1642 }
1643 next = advance();
1644 }
1645 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1646 appendStringToken(TokenType.STRING, getString(start, 0));
1647 return advance();
1648 }
1649 int tokenizeSingleLineString(int next, int quoteChar, int start) {
1650 while (next != quoteChar) {
1651 if (next == 0x5c) {
1652 next = advance();
1653 } else if (next == 0x24) {
1654 appendStringToken(TokenType.STRING, getString(start, -1));
1655 beginToken();
1656 next = tokenizeStringInterpolation(start);
1657 start = offset;
1658 continue;
1659 }
1660 if (next <= 0xd && (next == 0xa || next == 0xd || next == -1)) {
1661 reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
1662 appendStringToken(TokenType.STRING, getString(start, 0));
1663 return advance();
1664 }
1665 next = advance();
1666 }
1667 appendStringToken(TokenType.STRING, getString(start, 0));
1668 return advance();
1669 }
1670 int tokenizeSlashOrComment(int next) {
1671 next = advance();
1672 if (0x2a == next) {
1673 return tokenizeMultiLineComment(next);
1674 } else if (0x2f == next) {
1675 return tokenizeSingleLineComment(next);
1676 } else if (0x3d == next) {
1677 appendToken(TokenType.SLASH_EQ);
1678 return advance();
1679 } else {
1680 appendToken(TokenType.SLASH);
1681 return next;
1682 }
1683 }
1684 int tokenizeString(int next, int start, bool raw) {
1685 int quoteChar = next;
1686 next = advance();
1687 if (quoteChar == next) {
1688 next = advance();
1689 if (quoteChar == next) {
1690 return tokenizeMultiLineString(quoteChar, start, raw);
1691 } else {
1692 appendStringToken(TokenType.STRING, getString(start, -1));
1693 return next;
1694 }
1695 }
1696 if (raw) {
1697 return tokenizeSingleLineRawString(next, quoteChar, start);
1698 } else {
1699 return tokenizeSingleLineString(next, quoteChar, start);
1700 }
1701 }
1702 int tokenizeStringInterpolation(int start) {
1703 beginToken();
1704 int next = advance();
1705 if (next == 0x7b) {
1706 return tokenizeInterpolatedExpression(next, start);
1707 } else {
1708 return tokenizeInterpolatedIdentifier(next, start);
1709 }
1710 }
1711 int tokenizeTag(int next) {
1712 if (offset == 0) {
1713 if (peek() == 0x21) {
1714 do {
1715 next = advance();
1716 } while (next != 0xa && next != 0xd && next > 0);
1717 appendStringToken(TokenType.SCRIPT_TAG, getString(_tokenStart, 0));
1718 return next;
1719 }
1720 }
1721 appendToken(TokenType.HASH);
1722 return advance();
1723 }
1724 int tokenizeTilde(int next) {
1725 next = advance();
1726 if (next == 0x2f) {
1727 return select(0x3d, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
1728 } else {
1729 appendToken(TokenType.TILDE);
1730 return next;
1731 }
1732 }
1733 }
1734 /**
1735 * Instances of the class {@code KeywordTokenWithComment} implement a keyword to ken that is preceded
1736 * by comments.
1737 */
1738 class KeywordTokenWithComment extends KeywordToken {
1739 /**
1740 * The first comment in the list of comments that precede this token.
1741 */
1742 Token _precedingComment;
1743 /**
1744 * Initialize a newly created token to to represent the given keyword and to b e preceded by the
1745 * comments reachable from the given comment.
1746 * @param keyword the keyword being represented by this token
1747 * @param offset the offset from the beginning of the file to the first charac ter in the token
1748 * @param precedingComment the first comment in the list of comments that prec ede this token
1749 */
1750 KeywordTokenWithComment(Keyword keyword, int offset, Token precedingComment) : super(keyword, offset) {
1751 this._precedingComment = precedingComment;
1752 }
1753 Token get precedingComments => _precedingComment;
1754 }
1755 /**
1756 * Instances of the abstract class {@code KeywordState} represent a state in a s tate machine used to
1757 * scan keywords.
1758 */
1759 class KeywordState {
1760 /**
1761 * An empty transition table used by leaf states.
1762 */
1763 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>.fixedLength(26 );
1764 /**
1765 * The initial state in the state machine.
1766 */
1767 static KeywordState KEYWORD_STATE = createKeywordStateTable();
1768 /**
1769 * Create the next state in the state machine where we have already recognized the subset of
1770 * strings in the given array of strings starting at the given offset and havi ng the given length.
1771 * All of these strings have a common prefix and the next character is at the given start index.
1772 * @param start the index of the character in the strings used to transition t o a new state
1773 * @param strings an array containing all of the strings that will be recogniz ed by the state
1774 * machine
1775 * @param offset the offset of the first string in the array that has the pref ix that is assumed
1776 * to have been recognized by the time we reach the state being built
1777 * @param length the number of strings in the array that pass through the stat e being built
1778 * @return the state that was created
1779 */
1780 static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length) {
1781 List<KeywordState> result = new List<KeywordState>.fixedLength(26);
1782 assert(length != 0);
1783 int chunk = 0x0;
1784 int chunkStart = -1;
1785 bool isLeaf = false;
1786 for (int i = offset; i < offset + length; i++) {
1787 if (strings[i].length == start) {
1788 isLeaf = true;
1789 }
1790 if (strings[i].length > start) {
1791 int c = strings[i].charCodeAt(start);
1792 if (chunk != c) {
1793 if (chunkStart != -1) {
1794 result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, i - chunkStart);
1795 }
1796 chunkStart = i;
1797 chunk = c;
1798 }
1799 }
1800 }
1801 if (chunkStart != -1) {
1802 assert(result[chunk - 0x61] == null);
1803 result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkS tart, offset + length - chunkStart);
1804 } else {
1805 assert(length == 1);
1806 return new KeywordState(_EMPTY_TABLE, strings[offset]);
1807 }
1808 if (isLeaf) {
1809 return new KeywordState(result, strings[offset]);
1810 } else {
1811 return new KeywordState(result, null);
1812 }
1813 }
1814 /**
1815 * Create the initial state in the state machine.
1816 * @return the state that was created
1817 */
1818 static KeywordState createKeywordStateTable() {
1819 List<Keyword> values2 = Keyword.values;
1820 List<String> strings = new List<String>.fixedLength(values2.length);
1821 for (int i = 0; i < values2.length; i++) {
1822 strings[i] = values2[i].syntax;
1823 }
1824 strings.sort();
1825 return computeKeywordStateTable(0, strings, 0, strings.length);
1826 }
1827 /**
1828 * A table mapping characters to the states to which those characters will tra nsition. (The index
1829 * into the array is the offset from the character {@code 'a'} to the transiti oning character.)
1830 */
1831 List<KeywordState> _table;
1832 /**
1833 * The keyword that is recognized by this state, or {@code null} if this state is not a terminal
1834 * state.
1835 */
1836 Keyword _keyword2;
1837 /**
1838 * Initialize a newly created state to have the given transitions and to recog nize the keyword
1839 * with the given syntax.
1840 * @param table a table mapping characters to the states to which those charac ters will transition
1841 * @param syntax the syntax of the keyword that is recognized by the state
1842 */
1843 KeywordState(List<KeywordState> table, String syntax) {
1844 this._table = table;
1845 this._keyword2 = (syntax == null) ? null : Keyword.keywords[syntax];
1846 }
1847 /**
1848 * Return the keyword that was recognized by this state, or {@code null} if th is state does not
1849 * recognized a keyword.
1850 * @return the keyword that was matched by reaching this state
1851 */
1852 Keyword keyword() => _keyword2;
1853 /**
1854 * Return the state that follows this state on a transition of the given chara cter, or{@code null} if there is no valid state reachable from this state with s uch a transition.
1855 * @param c the character used to transition from this state to another state
1856 * @return the state that follows this state on a transition of the given char acter
1857 */
1858 KeywordState next(int c) => _table[c - 0x61];
1859 }
OLDNEW
« no previous file with comments | « pkg/analyzer-experimental/lib/src/generated/parser.dart ('k') | pkg/analyzer-experimental/lib/src/generated/source.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698