| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.src.dart.scanner.scanner; | 5 library analyzer.src.dart.scanner.scanner; |
| 6 | 6 |
| 7 import 'package:analyzer/dart/ast/token.dart'; | 7 import 'package:analyzer/dart/ast/token.dart'; |
| 8 import 'package:analyzer/src/dart/ast/token.dart'; | 8 import 'package:analyzer/src/dart/ast/token.dart'; |
| 9 import 'package:analyzer/src/dart/scanner/reader.dart'; | 9 import 'package:analyzer/src/dart/scanner/reader.dart'; |
| 10 import 'package:analyzer/src/generated/error.dart'; | 10 import 'package:analyzer/src/generated/error.dart'; |
| 11 import 'package:analyzer/src/generated/java_engine.dart'; | 11 import 'package:analyzer/src/generated/java_engine.dart'; |
| 12 import 'package:analyzer/src/generated/source.dart'; | 12 import 'package:analyzer/src/generated/source.dart'; |
| 13 import 'package:charcode/ascii.dart'; |
| 13 | 14 |
| 14 /** | 15 /** |
| 15 * A state in a state machine used to scan keywords. | 16 * A state in a state machine used to scan keywords. |
| 16 */ | 17 */ |
| 17 class KeywordState { | 18 class KeywordState { |
| 18 /** | 19 /** |
| 19 * An empty transition table used by leaf states. | 20 * An empty transition table used by leaf states. |
| 20 */ | 21 */ |
| 21 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26); | 22 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26); |
| 22 | 23 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 50 * Return the keyword that was recognized by this state, or `null` if this | 51 * Return the keyword that was recognized by this state, or `null` if this |
| 51 * state does not recognized a keyword. | 52 * state does not recognized a keyword. |
| 52 */ | 53 */ |
| 53 Keyword keyword() => _keyword; | 54 Keyword keyword() => _keyword; |
| 54 | 55 |
| 55 /** | 56 /** |
| 56 * Return the state that follows this state on a transition of the given | 57 * Return the state that follows this state on a transition of the given |
| 57 * [character], or `null` if there is no valid state reachable from this state | 58 * [character], or `null` if there is no valid state reachable from this state |
| 58 * with such a transition. | 59 * with such a transition. |
| 59 */ | 60 */ |
| 60 KeywordState next(int character) => _table[character - 0x61]; | 61 KeywordState next(int character) => _table[character - $a]; |
| 61 | 62 |
| 62 /** | 63 /** |
| 63 * Create the next state in the state machine where we have already recognized | 64 * Create the next state in the state machine where we have already recognized |
| 64 * the subset of strings in the given array of [strings] starting at the given | 65 * the subset of strings in the given array of [strings] starting at the given |
| 65 * [offset] and having the given [length]. All of these strings have a common | 66 * [offset] and having the given [length]. All of these strings have a common |
| 66 * prefix and the next character is at the given [start] index. | 67 * prefix and the next character is at the given [start] index. |
| 67 */ | 68 */ |
| 68 static KeywordState _computeKeywordStateTable( | 69 static KeywordState _computeKeywordStateTable( |
| 69 int start, List<String> strings, int offset, int length) { | 70 int start, List<String> strings, int offset, int length) { |
| 70 List<KeywordState> result = new List<KeywordState>(26); | 71 List<KeywordState> result = new List<KeywordState>(26); |
| 71 assert(length != 0); | 72 assert(length != 0); |
| 72 int chunk = 0x0; | 73 int chunk = $nul; |
| 73 int chunkStart = -1; | 74 int chunkStart = -1; |
| 74 bool isLeaf = false; | 75 bool isLeaf = false; |
| 75 for (int i = offset; i < offset + length; i++) { | 76 for (int i = offset; i < offset + length; i++) { |
| 76 if (strings[i].length == start) { | 77 if (strings[i].length == start) { |
| 77 isLeaf = true; | 78 isLeaf = true; |
| 78 } | 79 } |
| 79 if (strings[i].length > start) { | 80 if (strings[i].length > start) { |
| 80 int c = strings[i].codeUnitAt(start); | 81 int c = strings[i].codeUnitAt(start); |
| 81 if (chunk != c) { | 82 if (chunk != c) { |
| 82 if (chunkStart != -1) { | 83 if (chunkStart != -1) { |
| 83 result[chunk - 0x61] = _computeKeywordStateTable( | 84 result[chunk - $a] = _computeKeywordStateTable( |
| 84 start + 1, strings, chunkStart, i - chunkStart); | 85 start + 1, strings, chunkStart, i - chunkStart); |
| 85 } | 86 } |
| 86 chunkStart = i; | 87 chunkStart = i; |
| 87 chunk = c; | 88 chunk = c; |
| 88 } | 89 } |
| 89 } | 90 } |
| 90 } | 91 } |
| 91 if (chunkStart != -1) { | 92 if (chunkStart != -1) { |
| 92 assert(result[chunk - 0x61] == null); | 93 assert(result[chunk - $a] == null); |
| 93 result[chunk - 0x61] = _computeKeywordStateTable( | 94 result[chunk - $a] = _computeKeywordStateTable( |
| 94 start + 1, strings, chunkStart, offset + length - chunkStart); | 95 start + 1, strings, chunkStart, offset + length - chunkStart); |
| 95 } else { | 96 } else { |
| 96 assert(length == 1); | 97 assert(length == 1); |
| 97 return new KeywordState(_EMPTY_TABLE, strings[offset]); | 98 return new KeywordState(_EMPTY_TABLE, strings[offset]); |
| 98 } | 99 } |
| 99 if (isLeaf) { | 100 if (isLeaf) { |
| 100 return new KeywordState(result, strings[offset]); | 101 return new KeywordState(result, strings[offset]); |
| 101 } else { | 102 } else { |
| 102 return new KeywordState(result, null); | 103 return new KeywordState(result, null); |
| 103 } | 104 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 */ | 201 */ |
| 201 bool _hasUnmatchedGroups = false; | 202 bool _hasUnmatchedGroups = false; |
| 202 | 203 |
| 203 /** | 204 /** |
| 204 * A flag indicating whether to parse generic method comments, of the form | 205 * A flag indicating whether to parse generic method comments, of the form |
| 205 * `/*=T*/` and `/*<T>*/`. | 206 * `/*=T*/` and `/*<T>*/`. |
| 206 */ | 207 */ |
| 207 bool scanGenericMethodComments = false; | 208 bool scanGenericMethodComments = false; |
| 208 | 209 |
| 209 /** | 210 /** |
| 211 * A flag indicating whether the lazy compound assignment operators '&&=' and |
| 212 * '||=' are enabled. |
| 213 */ |
| 214 bool scanLazyAssignmentOperators = false; |
| 215 |
| 216 /** |
| 210 * Initialize a newly created scanner to scan characters from the given | 217 * Initialize a newly created scanner to scan characters from the given |
| 211 * [source]. The given character [_reader] will be used to read the characters | 218 * [source]. The given character [_reader] will be used to read the characters |
| 212 * in the source. The given [_errorListener] will be informed of any errors | 219 * in the source. The given [_errorListener] will be informed of any errors |
| 213 * that are found. | 220 * that are found. |
| 214 */ | 221 */ |
| 215 Scanner(this.source, this._reader, this._errorListener) { | 222 Scanner(this.source, this._reader, this._errorListener) { |
| 216 _tokens = new Token(TokenType.EOF, -1); | 223 _tokens = new Token(TokenType.EOF, -1); |
| 217 _tokens.setNext(_tokens); | 224 _tokens.setNext(_tokens); |
| 218 _tail = _tokens; | 225 _tail = _tokens; |
| 219 _tokenStart = -1; | 226 _tokenStart = -1; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 * method is intended to be used by subclasses that copy existing tokens and | 260 * method is intended to be used by subclasses that copy existing tokens and |
| 254 * should not normally be used because it will fail to correctly associate any | 261 * should not normally be used because it will fail to correctly associate any |
| 255 * comments with the token being passed in. | 262 * comments with the token being passed in. |
| 256 */ | 263 */ |
| 257 void appendToken(Token token) { | 264 void appendToken(Token token) { |
| 258 _tail = _tail.setNext(token); | 265 _tail = _tail.setNext(token); |
| 259 } | 266 } |
| 260 | 267 |
| 261 int bigSwitch(int next) { | 268 int bigSwitch(int next) { |
| 262 _beginToken(); | 269 _beginToken(); |
| 263 if (next == 0xD) { | 270 if (next == $cr) { |
| 264 // '\r' | 271 // '\r' |
| 265 next = _reader.advance(); | 272 next = _reader.advance(); |
| 266 if (next == 0xA) { | 273 if (next == $lf) { |
| 267 // '\n' | 274 // '\n' |
| 268 next = _reader.advance(); | 275 next = _reader.advance(); |
| 269 } | 276 } |
| 270 recordStartOfLine(); | 277 recordStartOfLine(); |
| 271 return next; | 278 return next; |
| 272 } else if (next == 0xA) { | 279 } else if (next == $lf) { |
| 273 // '\n' | 280 // '\n' |
| 274 next = _reader.advance(); | 281 next = _reader.advance(); |
| 275 recordStartOfLine(); | 282 recordStartOfLine(); |
| 276 return next; | 283 return next; |
| 277 } else if (next == 0x9 || next == 0x20) { | 284 } else if (next == $tab || next == $space) { |
| 278 // '\t' || ' ' | 285 // '\t' || ' ' |
| 279 return _reader.advance(); | 286 return _reader.advance(); |
| 280 } | 287 } |
| 281 if (next == 0x72) { | 288 if (next == $r) { |
| 282 // 'r' | 289 // 'r' |
| 283 int peek = _reader.peek(); | 290 int peek = _reader.peek(); |
| 284 if (peek == 0x22 || peek == 0x27) { | 291 if (peek == $double_quote || peek == $single_quote) { |
| 285 // '"' || "'" | 292 // '"' || "'" |
| 286 int start = _reader.offset; | 293 int start = _reader.offset; |
| 287 return _tokenizeString(_reader.advance(), start, true); | 294 return _tokenizeString(_reader.advance(), start, true); |
| 288 } | 295 } |
| 289 } | 296 } |
| 290 if (0x61 <= next && next <= 0x7A) { | 297 if ($a <= next && next <= $z) { |
| 291 // 'a'-'z' | 298 // 'a'-'z' |
| 292 return _tokenizeKeywordOrIdentifier(next, true); | 299 return _tokenizeKeywordOrIdentifier(next, true); |
| 293 } | 300 } |
| 294 if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) { | 301 if (($A <= next && next <= $Z) || next == $_ || next == $$) { |
| 295 // 'A'-'Z' || '_' || '$' | 302 // 'A'-'Z' || '_' || '$' |
| 296 return _tokenizeIdentifier(next, _reader.offset, true); | 303 return _tokenizeIdentifier(next, _reader.offset, true); |
| 297 } | 304 } |
| 298 if (next == 0x3C) { | 305 if (next == $lt) { |
| 299 // '<' | 306 // '<' |
| 300 return _tokenizeLessThan(next); | 307 return _tokenizeLessThan(next); |
| 301 } | 308 } |
| 302 if (next == 0x3E) { | 309 if (next == $gt) { |
| 303 // '>' | 310 // '>' |
| 304 return _tokenizeGreaterThan(next); | 311 return _tokenizeGreaterThan(next); |
| 305 } | 312 } |
| 306 if (next == 0x3D) { | 313 if (next == $equal) { |
| 307 // '=' | 314 // '=' |
| 308 return _tokenizeEquals(next); | 315 return _tokenizeEquals(next); |
| 309 } | 316 } |
| 310 if (next == 0x21) { | 317 if (next == $exclamation) { |
| 311 // '!' | 318 // '!' |
| 312 return _tokenizeExclamation(next); | 319 return _tokenizeExclamation(next); |
| 313 } | 320 } |
| 314 if (next == 0x2B) { | 321 if (next == $plus) { |
| 315 // '+' | 322 // '+' |
| 316 return _tokenizePlus(next); | 323 return _tokenizePlus(next); |
| 317 } | 324 } |
| 318 if (next == 0x2D) { | 325 if (next == $minus) { |
| 319 // '-' | 326 // '-' |
| 320 return _tokenizeMinus(next); | 327 return _tokenizeMinus(next); |
| 321 } | 328 } |
| 322 if (next == 0x2A) { | 329 if (next == $asterisk) { |
| 323 // '*' | 330 // '*' |
| 324 return _tokenizeMultiply(next); | 331 return _tokenizeMultiply(next); |
| 325 } | 332 } |
| 326 if (next == 0x25) { | 333 if (next == $percent) { |
| 327 // '%' | 334 // '%' |
| 328 return _tokenizePercent(next); | 335 return _tokenizePercent(next); |
| 329 } | 336 } |
| 330 if (next == 0x26) { | 337 if (next == $ampersand) { |
| 331 // '&' | 338 // '&' |
| 332 return _tokenizeAmpersand(next); | 339 return _tokenizeAmpersand(next); |
| 333 } | 340 } |
| 334 if (next == 0x7C) { | 341 if (next == $bar) { |
| 335 // '|' | 342 // '|' |
| 336 return _tokenizeBar(next); | 343 return _tokenizeBar(next); |
| 337 } | 344 } |
| 338 if (next == 0x5E) { | 345 if (next == $caret) { |
| 339 // '^' | 346 // '^' |
| 340 return _tokenizeCaret(next); | 347 return _tokenizeCaret(next); |
| 341 } | 348 } |
| 342 if (next == 0x5B) { | 349 if (next == $open_bracket) { |
| 343 // '[' | 350 // '[' |
| 344 return _tokenizeOpenSquareBracket(next); | 351 return _tokenizeOpenSquareBracket(next); |
| 345 } | 352 } |
| 346 if (next == 0x7E) { | 353 if (next == $tilde) { |
| 347 // '~' | 354 // '~' |
| 348 return _tokenizeTilde(next); | 355 return _tokenizeTilde(next); |
| 349 } | 356 } |
| 350 if (next == 0x5C) { | 357 if (next == $backslash) { |
| 351 // '\\' | 358 // '\\' |
| 352 _appendTokenOfType(TokenType.BACKSLASH); | 359 _appendTokenOfType(TokenType.BACKSLASH); |
| 353 return _reader.advance(); | 360 return _reader.advance(); |
| 354 } | 361 } |
| 355 if (next == 0x23) { | 362 if (next == $hash) { |
| 356 // '#' | 363 // '#' |
| 357 return _tokenizeTag(next); | 364 return _tokenizeTag(next); |
| 358 } | 365 } |
| 359 if (next == 0x28) { | 366 if (next == $open_paren) { |
| 360 // '(' | 367 // '(' |
| 361 _appendBeginToken(TokenType.OPEN_PAREN); | 368 _appendBeginToken(TokenType.OPEN_PAREN); |
| 362 return _reader.advance(); | 369 return _reader.advance(); |
| 363 } | 370 } |
| 364 if (next == 0x29) { | 371 if (next == $close_paren) { |
| 365 // ')' | 372 // ')' |
| 366 _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN); | 373 _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN); |
| 367 return _reader.advance(); | 374 return _reader.advance(); |
| 368 } | 375 } |
| 369 if (next == 0x2C) { | 376 if (next == $comma) { |
| 370 // ',' | 377 // ',' |
| 371 _appendTokenOfType(TokenType.COMMA); | 378 _appendTokenOfType(TokenType.COMMA); |
| 372 return _reader.advance(); | 379 return _reader.advance(); |
| 373 } | 380 } |
| 374 if (next == 0x3A) { | 381 if (next == $colon) { |
| 375 // ':' | 382 // ':' |
| 376 _appendTokenOfType(TokenType.COLON); | 383 _appendTokenOfType(TokenType.COLON); |
| 377 return _reader.advance(); | 384 return _reader.advance(); |
| 378 } | 385 } |
| 379 if (next == 0x3B) { | 386 if (next == $semicolon) { |
| 380 // ';' | 387 // ';' |
| 381 _appendTokenOfType(TokenType.SEMICOLON); | 388 _appendTokenOfType(TokenType.SEMICOLON); |
| 382 return _reader.advance(); | 389 return _reader.advance(); |
| 383 } | 390 } |
| 384 if (next == 0x3F) { | 391 if (next == $question) { |
| 385 // '?' | 392 // '?' |
| 386 return _tokenizeQuestion(); | 393 return _tokenizeQuestion(); |
| 387 } | 394 } |
| 388 if (next == 0x5D) { | 395 if (next == $close_bracket) { |
| 389 // ']' | 396 // ']' |
| 390 _appendEndToken( | 397 _appendEndToken( |
| 391 TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET); | 398 TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET); |
| 392 return _reader.advance(); | 399 return _reader.advance(); |
| 393 } | 400 } |
| 394 if (next == 0x60) { | 401 if (next == $backquote) { |
| 395 // '`' | 402 // '`' |
| 396 _appendTokenOfType(TokenType.BACKPING); | 403 _appendTokenOfType(TokenType.BACKPING); |
| 397 return _reader.advance(); | 404 return _reader.advance(); |
| 398 } | 405 } |
| 399 if (next == 0x7B) { | 406 if (next == $lbrace) { |
| 400 // '{' | 407 // '{' |
| 401 _appendBeginToken(TokenType.OPEN_CURLY_BRACKET); | 408 _appendBeginToken(TokenType.OPEN_CURLY_BRACKET); |
| 402 return _reader.advance(); | 409 return _reader.advance(); |
| 403 } | 410 } |
| 404 if (next == 0x7D) { | 411 if (next == $rbrace) { |
| 405 // '}' | 412 // '}' |
| 406 _appendEndToken( | 413 _appendEndToken( |
| 407 TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET); | 414 TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET); |
| 408 return _reader.advance(); | 415 return _reader.advance(); |
| 409 } | 416 } |
| 410 if (next == 0x2F) { | 417 if (next == $slash) { |
| 411 // '/' | 418 // '/' |
| 412 return _tokenizeSlashOrComment(next); | 419 return _tokenizeSlashOrComment(next); |
| 413 } | 420 } |
| 414 if (next == 0x40) { | 421 if (next == $at) { |
| 415 // '@' | 422 // '@' |
| 416 _appendTokenOfType(TokenType.AT); | 423 _appendTokenOfType(TokenType.AT); |
| 417 return _reader.advance(); | 424 return _reader.advance(); |
| 418 } | 425 } |
| 419 if (next == 0x22 || next == 0x27) { | 426 if (next == $double_quote || next == $single_quote) { |
| 420 // '"' || "'" | 427 // '"' || "'" |
| 421 return _tokenizeString(next, _reader.offset, false); | 428 return _tokenizeString(next, _reader.offset, false); |
| 422 } | 429 } |
| 423 if (next == 0x2E) { | 430 if (next == $dot) { |
| 424 // '.' | 431 // '.' |
| 425 return _tokenizeDotOrNumber(next); | 432 return _tokenizeDotOrNumber(next); |
| 426 } | 433 } |
| 427 if (next == 0x30) { | 434 if (next == $0) { |
| 428 // '0' | 435 // '0' |
| 429 return _tokenizeHexOrNumber(next); | 436 return _tokenizeHexOrNumber(next); |
| 430 } | 437 } |
| 431 if (0x31 <= next && next <= 0x39) { | 438 if ($1 <= next && next <= $9) { |
| 432 // '1'-'9' | 439 // '1'-'9' |
| 433 return _tokenizeNumber(next); | 440 return _tokenizeNumber(next); |
| 434 } | 441 } |
| 435 if (next == -1) { | 442 if (next == -1) { |
| 436 // EOF | 443 // EOF |
| 437 return -1; | 444 return -1; |
| 438 } | 445 } |
| 439 _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]); | 446 _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]); |
| 440 return _reader.advance(); | 447 return _reader.advance(); |
| 441 } | 448 } |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 | 648 |
| 642 /** | 649 /** |
| 643 * Checks if [value] is the start of a generic method type annotation comment. | 650 * Checks if [value] is the start of a generic method type annotation comment. |
| 644 * | 651 * |
| 645 * This can either be of the form `/*<T>*/` or `/*=T*/`. The token type is | 652 * This can either be of the form `/*<T>*/` or `/*=T*/`. The token type is |
| 646 * returned, or null if it was not a generic method comment. | 653 * returned, or null if it was not a generic method comment. |
| 647 */ | 654 */ |
| 648 TokenType _matchGenericMethodCommentType(String value) { | 655 TokenType _matchGenericMethodCommentType(String value) { |
| 649 if (scanGenericMethodComments) { | 656 if (scanGenericMethodComments) { |
| 650 // Match /*< and >*/ | 657 // Match /*< and >*/ |
| 651 if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3C) && | 658 if (StringUtilities.startsWith3(value, 0, $slash, $asterisk, $lt) && |
| 652 StringUtilities.endsWith3(value, 0x3E, 0x2A, 0x2F)) { | 659 StringUtilities.endsWith3(value, $gt, $asterisk, $slash)) { |
| 653 return TokenType.GENERIC_METHOD_TYPE_LIST; | 660 return TokenType.GENERIC_METHOD_TYPE_LIST; |
| 654 } | 661 } |
| 655 // Match /*= | 662 // Match /*= |
| 656 if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3D)) { | 663 if (StringUtilities.startsWith3(value, 0, $slash, $asterisk, $equal)) { |
| 657 return TokenType.GENERIC_METHOD_TYPE_ASSIGN; | 664 return TokenType.GENERIC_METHOD_TYPE_ASSIGN; |
| 658 } | 665 } |
| 659 } | 666 } |
| 660 return null; | 667 return null; |
| 661 } | 668 } |
| 662 | 669 |
| 663 /** | 670 /** |
| 664 * Report an error at the current offset. The [errorCode] is the error code | 671 * Report an error at the current offset. The [errorCode] is the error code |
| 665 * indicating the nature of the error. The [arguments] are any arguments | 672 * indicating the nature of the error. The [arguments] are any arguments |
| 666 * needed to complete the error message | 673 * needed to complete the error message |
| (...skipping 20 matching lines...) Expand all Loading... |
| 687 if (next == choice) { | 694 if (next == choice) { |
| 688 _appendTokenOfTypeWithOffset(yesType, offset); | 695 _appendTokenOfTypeWithOffset(yesType, offset); |
| 689 return _reader.advance(); | 696 return _reader.advance(); |
| 690 } else { | 697 } else { |
| 691 _appendTokenOfTypeWithOffset(noType, offset); | 698 _appendTokenOfTypeWithOffset(noType, offset); |
| 692 return next; | 699 return next; |
| 693 } | 700 } |
| 694 } | 701 } |
| 695 | 702 |
| 696 int _tokenizeAmpersand(int next) { | 703 int _tokenizeAmpersand(int next) { |
| 697 // && &= & | 704 // &&= && &= & |
| 698 next = _reader.advance(); | 705 next = _reader.advance(); |
| 699 if (next == 0x26) { | 706 if (next == $ampersand) { |
| 707 next = _reader.advance(); |
| 708 if (scanLazyAssignmentOperators && next == $equal) { |
| 709 _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND_EQ); |
| 710 return _reader.advance(); |
| 711 } |
| 700 _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND); | 712 _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND); |
| 701 return _reader.advance(); | 713 return next; |
| 702 } else if (next == 0x3D) { | 714 } else if (next == $equal) { |
| 703 _appendTokenOfType(TokenType.AMPERSAND_EQ); | 715 _appendTokenOfType(TokenType.AMPERSAND_EQ); |
| 704 return _reader.advance(); | 716 return _reader.advance(); |
| 705 } else { | 717 } else { |
| 706 _appendTokenOfType(TokenType.AMPERSAND); | 718 _appendTokenOfType(TokenType.AMPERSAND); |
| 707 return next; | 719 return next; |
| 708 } | 720 } |
| 709 } | 721 } |
| 710 | 722 |
| 711 int _tokenizeBar(int next) { | 723 int _tokenizeBar(int next) { |
| 712 // | || |= | 724 // ||= || |= | |
| 713 next = _reader.advance(); | 725 next = _reader.advance(); |
| 714 if (next == 0x7C) { | 726 if (next == $bar) { |
| 727 next = _reader.advance(); |
| 728 if (scanLazyAssignmentOperators && next == $equal) { |
| 729 _appendTokenOfType(TokenType.BAR_BAR_EQ); |
| 730 return _reader.advance(); |
| 731 } |
| 715 _appendTokenOfType(TokenType.BAR_BAR); | 732 _appendTokenOfType(TokenType.BAR_BAR); |
| 716 return _reader.advance(); | 733 return next; |
| 717 } else if (next == 0x3D) { | 734 } else if (next == $equal) { |
| 718 _appendTokenOfType(TokenType.BAR_EQ); | 735 _appendTokenOfType(TokenType.BAR_EQ); |
| 719 return _reader.advance(); | 736 return _reader.advance(); |
| 720 } else { | 737 } else { |
| 721 _appendTokenOfType(TokenType.BAR); | 738 _appendTokenOfType(TokenType.BAR); |
| 722 return next; | 739 return next; |
| 723 } | 740 } |
| 724 } | 741 } |
| 725 | 742 |
| 726 int _tokenizeCaret(int next) => | 743 int _tokenizeCaret(int next) => |
| 727 _select(0x3D, TokenType.CARET_EQ, TokenType.CARET); | 744 _select($equal, TokenType.CARET_EQ, TokenType.CARET); |
| 728 | 745 |
| 729 int _tokenizeDotOrNumber(int next) { | 746 int _tokenizeDotOrNumber(int next) { |
| 730 int start = _reader.offset; | 747 int start = _reader.offset; |
| 731 next = _reader.advance(); | 748 next = _reader.advance(); |
| 732 if (0x30 <= next && next <= 0x39) { | 749 if ($0 <= next && next <= $9) { |
| 733 return _tokenizeFractionPart(next, start); | 750 return _tokenizeFractionPart(next, start); |
| 734 } else if (0x2E == next) { | 751 } else if ($dot == next) { |
| 735 return _select( | 752 return _select( |
| 736 0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD); | 753 $dot, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD); |
| 737 } else { | 754 } else { |
| 738 _appendTokenOfType(TokenType.PERIOD); | 755 _appendTokenOfType(TokenType.PERIOD); |
| 739 return next; | 756 return next; |
| 740 } | 757 } |
| 741 } | 758 } |
| 742 | 759 |
| 743 int _tokenizeEquals(int next) { | 760 int _tokenizeEquals(int next) { |
| 744 // = == => | 761 // = == => |
| 745 next = _reader.advance(); | 762 next = _reader.advance(); |
| 746 if (next == 0x3D) { | 763 if (next == $equal) { |
| 747 _appendTokenOfType(TokenType.EQ_EQ); | 764 _appendTokenOfType(TokenType.EQ_EQ); |
| 748 return _reader.advance(); | 765 return _reader.advance(); |
| 749 } else if (next == 0x3E) { | 766 } else if (next == $gt) { |
| 750 _appendTokenOfType(TokenType.FUNCTION); | 767 _appendTokenOfType(TokenType.FUNCTION); |
| 751 return _reader.advance(); | 768 return _reader.advance(); |
| 752 } | 769 } |
| 753 _appendTokenOfType(TokenType.EQ); | 770 _appendTokenOfType(TokenType.EQ); |
| 754 return next; | 771 return next; |
| 755 } | 772 } |
| 756 | 773 |
| 757 int _tokenizeExclamation(int next) { | 774 int _tokenizeExclamation(int next) { |
| 758 // ! != | 775 // ! != |
| 759 next = _reader.advance(); | 776 next = _reader.advance(); |
| 760 if (next == 0x3D) { | 777 if (next == $equal) { |
| 761 _appendTokenOfType(TokenType.BANG_EQ); | 778 _appendTokenOfType(TokenType.BANG_EQ); |
| 762 return _reader.advance(); | 779 return _reader.advance(); |
| 763 } | 780 } |
| 764 _appendTokenOfType(TokenType.BANG); | 781 _appendTokenOfType(TokenType.BANG); |
| 765 return next; | 782 return next; |
| 766 } | 783 } |
| 767 | 784 |
| 768 int _tokenizeExponent(int next) { | 785 int _tokenizeExponent(int next) { |
| 769 if (next == 0x2B || next == 0x2D) { | 786 if (next == $plus || next == $minus) { |
| 770 next = _reader.advance(); | 787 next = _reader.advance(); |
| 771 } | 788 } |
| 772 bool hasDigits = false; | 789 bool hasDigits = false; |
| 773 while (true) { | 790 while (true) { |
| 774 if (0x30 <= next && next <= 0x39) { | 791 if ($0 <= next && next <= $9) { |
| 775 hasDigits = true; | 792 hasDigits = true; |
| 776 } else { | 793 } else { |
| 777 if (!hasDigits) { | 794 if (!hasDigits) { |
| 778 _reportError(ScannerErrorCode.MISSING_DIGIT); | 795 _reportError(ScannerErrorCode.MISSING_DIGIT); |
| 779 } | 796 } |
| 780 return next; | 797 return next; |
| 781 } | 798 } |
| 782 next = _reader.advance(); | 799 next = _reader.advance(); |
| 783 } | 800 } |
| 784 } | 801 } |
| 785 | 802 |
| 786 int _tokenizeFractionPart(int next, int start) { | 803 int _tokenizeFractionPart(int next, int start) { |
| 787 bool done = false; | 804 bool done = false; |
| 788 bool hasDigit = false; | 805 bool hasDigit = false; |
| 789 LOOP: while (!done) { | 806 LOOP: while (!done) { |
| 790 if (0x30 <= next && next <= 0x39) { | 807 if ($0 <= next && next <= $9) { |
| 791 hasDigit = true; | 808 hasDigit = true; |
| 792 } else if (0x65 == next || 0x45 == next) { | 809 } else if ($e == next || $E == next) { |
| 793 hasDigit = true; | 810 hasDigit = true; |
| 794 next = _tokenizeExponent(_reader.advance()); | 811 next = _tokenizeExponent(_reader.advance()); |
| 795 done = true; | 812 done = true; |
| 796 continue LOOP; | 813 continue LOOP; |
| 797 } else { | 814 } else { |
| 798 done = true; | 815 done = true; |
| 799 continue LOOP; | 816 continue LOOP; |
| 800 } | 817 } |
| 801 next = _reader.advance(); | 818 next = _reader.advance(); |
| 802 } | 819 } |
| 803 if (!hasDigit) { | 820 if (!hasDigit) { |
| 804 _appendStringToken(TokenType.INT, _reader.getString(start, -2)); | 821 _appendStringToken(TokenType.INT, _reader.getString(start, -2)); |
| 805 if (0x2E == next) { | 822 if ($dot == next) { |
| 806 return _selectWithOffset(0x2E, TokenType.PERIOD_PERIOD_PERIOD, | 823 return _selectWithOffset($dot, TokenType.PERIOD_PERIOD_PERIOD, |
| 807 TokenType.PERIOD_PERIOD, _reader.offset - 1); | 824 TokenType.PERIOD_PERIOD, _reader.offset - 1); |
| 808 } | 825 } |
| 809 _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1); | 826 _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1); |
| 810 return bigSwitch(next); | 827 return bigSwitch(next); |
| 811 } | 828 } |
| 812 _appendStringToken( | 829 _appendStringToken( |
| 813 TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1)); | 830 TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1)); |
| 814 return next; | 831 return next; |
| 815 } | 832 } |
| 816 | 833 |
| 817 int _tokenizeGreaterThan(int next) { | 834 int _tokenizeGreaterThan(int next) { |
| 818 // > >= >> >>= | 835 // > >= >> >>= |
| 819 next = _reader.advance(); | 836 next = _reader.advance(); |
| 820 if (0x3D == next) { | 837 if ($equal == next) { |
| 821 _appendTokenOfType(TokenType.GT_EQ); | 838 _appendTokenOfType(TokenType.GT_EQ); |
| 822 return _reader.advance(); | 839 return _reader.advance(); |
| 823 } else if (0x3E == next) { | 840 } else if ($gt == next) { |
| 824 next = _reader.advance(); | 841 next = _reader.advance(); |
| 825 if (0x3D == next) { | 842 if ($equal == next) { |
| 826 _appendTokenOfType(TokenType.GT_GT_EQ); | 843 _appendTokenOfType(TokenType.GT_GT_EQ); |
| 827 return _reader.advance(); | 844 return _reader.advance(); |
| 828 } else { | 845 } else { |
| 829 _appendTokenOfType(TokenType.GT_GT); | 846 _appendTokenOfType(TokenType.GT_GT); |
| 830 return next; | 847 return next; |
| 831 } | 848 } |
| 832 } else { | 849 } else { |
| 833 _appendTokenOfType(TokenType.GT); | 850 _appendTokenOfType(TokenType.GT); |
| 834 return next; | 851 return next; |
| 835 } | 852 } |
| 836 } | 853 } |
| 837 | 854 |
| 838 int _tokenizeHex(int next) { | 855 int _tokenizeHex(int next) { |
| 839 int start = _reader.offset - 1; | 856 int start = _reader.offset - 1; |
| 840 bool hasDigits = false; | 857 bool hasDigits = false; |
| 841 while (true) { | 858 while (true) { |
| 842 next = _reader.advance(); | 859 next = _reader.advance(); |
| 843 if ((0x30 <= next && next <= 0x39) || | 860 if (($0 <= next && next <= $9) || |
| 844 (0x41 <= next && next <= 0x46) || | 861 ($A <= next && next <= $F) || |
| 845 (0x61 <= next && next <= 0x66)) { | 862 ($a <= next && next <= $f)) { |
| 846 hasDigits = true; | 863 hasDigits = true; |
| 847 } else { | 864 } else { |
| 848 if (!hasDigits) { | 865 if (!hasDigits) { |
| 849 _reportError(ScannerErrorCode.MISSING_HEX_DIGIT); | 866 _reportError(ScannerErrorCode.MISSING_HEX_DIGIT); |
| 850 } | 867 } |
| 851 _appendStringToken( | 868 _appendStringToken( |
| 852 TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1)); | 869 TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1)); |
| 853 return next; | 870 return next; |
| 854 } | 871 } |
| 855 } | 872 } |
| 856 } | 873 } |
| 857 | 874 |
| 858 int _tokenizeHexOrNumber(int next) { | 875 int _tokenizeHexOrNumber(int next) { |
| 859 int x = _reader.peek(); | 876 int x = _reader.peek(); |
| 860 if (x == 0x78 || x == 0x58) { | 877 if (x == $x || x == $X) { |
| 861 _reader.advance(); | 878 _reader.advance(); |
| 862 return _tokenizeHex(x); | 879 return _tokenizeHex(x); |
| 863 } | 880 } |
| 864 return _tokenizeNumber(next); | 881 return _tokenizeNumber(next); |
| 865 } | 882 } |
| 866 | 883 |
| 867 int _tokenizeIdentifier(int next, int start, bool allowDollar) { | 884 int _tokenizeIdentifier(int next, int start, bool allowDollar) { |
| 868 while ((0x61 <= next && next <= 0x7A) || | 885 while (($a <= next && next <= $z) || |
| 869 (0x41 <= next && next <= 0x5A) || | 886 ($A <= next && next <= $Z) || |
| 870 (0x30 <= next && next <= 0x39) || | 887 ($0 <= next && next <= $9) || |
| 871 next == 0x5F || | 888 next == $_ || |
| 872 (next == 0x24 && allowDollar)) { | 889 (next == $$ && allowDollar)) { |
| 873 next = _reader.advance(); | 890 next = _reader.advance(); |
| 874 } | 891 } |
| 875 _appendStringToken( | 892 _appendStringToken( |
| 876 TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1)); | 893 TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1)); |
| 877 return next; | 894 return next; |
| 878 } | 895 } |
| 879 | 896 |
| 880 int _tokenizeInterpolatedExpression(int next, int start) { | 897 int _tokenizeInterpolatedExpression(int next, int start) { |
| 881 _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION); | 898 _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION); |
| 882 next = _reader.advance(); | 899 next = _reader.advance(); |
| 883 while (next != -1) { | 900 while (next != -1) { |
| 884 if (next == 0x7D) { | 901 if (next == $rbrace) { |
| 885 BeginToken begin = | 902 BeginToken begin = |
| 886 _findTokenMatchingClosingBraceInInterpolationExpression(); | 903 _findTokenMatchingClosingBraceInInterpolationExpression(); |
| 887 if (begin == null) { | 904 if (begin == null) { |
| 888 _beginToken(); | 905 _beginToken(); |
| 889 _appendTokenOfType(TokenType.CLOSE_CURLY_BRACKET); | 906 _appendTokenOfType(TokenType.CLOSE_CURLY_BRACKET); |
| 890 next = _reader.advance(); | 907 next = _reader.advance(); |
| 891 _beginToken(); | 908 _beginToken(); |
| 892 return next; | 909 return next; |
| 893 } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) { | 910 } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) { |
| 894 _beginToken(); | 911 _beginToken(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 907 } else { | 924 } else { |
| 908 next = bigSwitch(next); | 925 next = bigSwitch(next); |
| 909 } | 926 } |
| 910 } | 927 } |
| 911 return next; | 928 return next; |
| 912 } | 929 } |
| 913 | 930 |
| 914 int _tokenizeInterpolatedIdentifier(int next, int start) { | 931 int _tokenizeInterpolatedIdentifier(int next, int start) { |
| 915 _appendStringTokenWithOffset( | 932 _appendStringTokenWithOffset( |
| 916 TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0); | 933 TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0); |
| 917 if ((0x41 <= next && next <= 0x5A) || | 934 if (($A <= next && next <= $Z) || |
| 918 (0x61 <= next && next <= 0x7A) || | 935 ($a <= next && next <= $z) || |
| 919 next == 0x5F) { | 936 next == $_) { |
| 920 _beginToken(); | 937 _beginToken(); |
| 921 next = _tokenizeKeywordOrIdentifier(next, false); | 938 next = _tokenizeKeywordOrIdentifier(next, false); |
| 922 } | 939 } |
| 923 _beginToken(); | 940 _beginToken(); |
| 924 return next; | 941 return next; |
| 925 } | 942 } |
| 926 | 943 |
| 927 int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) { | 944 int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) { |
| 928 KeywordState state = KeywordState.KEYWORD_STATE; | 945 KeywordState state = KeywordState.KEYWORD_STATE; |
| 929 int start = _reader.offset; | 946 int start = _reader.offset; |
| 930 while (state != null && 0x61 <= next && next <= 0x7A) { | 947 while (state != null && $a <= next && next <= $z) { |
| 931 state = state.next(next); | 948 state = state.next(next); |
| 932 next = _reader.advance(); | 949 next = _reader.advance(); |
| 933 } | 950 } |
| 934 if (state == null || state.keyword() == null) { | 951 if (state == null || state.keyword() == null) { |
| 935 return _tokenizeIdentifier(next, start, allowDollar); | 952 return _tokenizeIdentifier(next, start, allowDollar); |
| 936 } | 953 } |
| 937 if ((0x41 <= next && next <= 0x5A) || | 954 if (($A <= next && next <= $Z) || |
| 938 (0x30 <= next && next <= 0x39) || | 955 ($0 <= next && next <= $9) || |
| 939 next == 0x5F || | 956 next == $_ || |
| 940 next == 0x24) { | 957 next == $$) { |
| 941 return _tokenizeIdentifier(next, start, allowDollar); | 958 return _tokenizeIdentifier(next, start, allowDollar); |
| 942 } else if (next < 128) { | 959 } else if (next < 128) { |
| 943 _appendKeywordToken(state.keyword()); | 960 _appendKeywordToken(state.keyword()); |
| 944 return next; | 961 return next; |
| 945 } else { | 962 } else { |
| 946 return _tokenizeIdentifier(next, start, allowDollar); | 963 return _tokenizeIdentifier(next, start, allowDollar); |
| 947 } | 964 } |
| 948 } | 965 } |
| 949 | 966 |
| 950 int _tokenizeLessThan(int next) { | 967 int _tokenizeLessThan(int next) { |
| 951 // < <= << <<= | 968 // < <= << <<= |
| 952 next = _reader.advance(); | 969 next = _reader.advance(); |
| 953 if (0x3D == next) { | 970 if ($equal == next) { |
| 954 _appendTokenOfType(TokenType.LT_EQ); | 971 _appendTokenOfType(TokenType.LT_EQ); |
| 955 return _reader.advance(); | 972 return _reader.advance(); |
| 956 } else if (0x3C == next) { | 973 } else if ($lt == next) { |
| 957 return _select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT); | 974 return _select($equal, TokenType.LT_LT_EQ, TokenType.LT_LT); |
| 958 } else { | 975 } else { |
| 959 _appendTokenOfType(TokenType.LT); | 976 _appendTokenOfType(TokenType.LT); |
| 960 return next; | 977 return next; |
| 961 } | 978 } |
| 962 } | 979 } |
| 963 | 980 |
| 964 int _tokenizeMinus(int next) { | 981 int _tokenizeMinus(int next) { |
| 965 // - -- -= | 982 // - -- -= |
| 966 next = _reader.advance(); | 983 next = _reader.advance(); |
| 967 if (next == 0x2D) { | 984 if (next == $minus) { |
| 968 _appendTokenOfType(TokenType.MINUS_MINUS); | 985 _appendTokenOfType(TokenType.MINUS_MINUS); |
| 969 return _reader.advance(); | 986 return _reader.advance(); |
| 970 } else if (next == 0x3D) { | 987 } else if (next == $equal) { |
| 971 _appendTokenOfType(TokenType.MINUS_EQ); | 988 _appendTokenOfType(TokenType.MINUS_EQ); |
| 972 return _reader.advance(); | 989 return _reader.advance(); |
| 973 } else { | 990 } else { |
| 974 _appendTokenOfType(TokenType.MINUS); | 991 _appendTokenOfType(TokenType.MINUS); |
| 975 return next; | 992 return next; |
| 976 } | 993 } |
| 977 } | 994 } |
| 978 | 995 |
| 979 int _tokenizeMultiLineComment(int next) { | 996 int _tokenizeMultiLineComment(int next) { |
| 980 int nesting = 1; | 997 int nesting = 1; |
| 981 next = _reader.advance(); | 998 next = _reader.advance(); |
| 982 while (true) { | 999 while (true) { |
| 983 if (-1 == next) { | 1000 if (-1 == next) { |
| 984 _reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT); | 1001 _reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT); |
| 985 _appendCommentToken( | 1002 _appendCommentToken( |
| 986 TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0)); | 1003 TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0)); |
| 987 return next; | 1004 return next; |
| 988 } else if (0x2A == next) { | 1005 } else if ($asterisk == next) { |
| 989 next = _reader.advance(); | 1006 next = _reader.advance(); |
| 990 if (0x2F == next) { | 1007 if ($slash == next) { |
| 991 --nesting; | 1008 --nesting; |
| 992 if (0 == nesting) { | 1009 if (0 == nesting) { |
| 993 _appendCommentToken(TokenType.MULTI_LINE_COMMENT, | 1010 _appendCommentToken(TokenType.MULTI_LINE_COMMENT, |
| 994 _reader.getString(_tokenStart, 0)); | 1011 _reader.getString(_tokenStart, 0)); |
| 995 return _reader.advance(); | 1012 return _reader.advance(); |
| 996 } else { | 1013 } else { |
| 997 next = _reader.advance(); | 1014 next = _reader.advance(); |
| 998 } | 1015 } |
| 999 } | 1016 } |
| 1000 } else if (0x2F == next) { | 1017 } else if ($slash == next) { |
| 1001 next = _reader.advance(); | 1018 next = _reader.advance(); |
| 1002 if (0x2A == next) { | 1019 if ($asterisk == next) { |
| 1003 next = _reader.advance(); | 1020 next = _reader.advance(); |
| 1004 ++nesting; | 1021 ++nesting; |
| 1005 } | 1022 } |
| 1006 } else if (next == 0xD) { | 1023 } else if (next == $cr) { |
| 1007 next = _reader.advance(); | 1024 next = _reader.advance(); |
| 1008 if (next == 0xA) { | 1025 if (next == $lf) { |
| 1009 next = _reader.advance(); | 1026 next = _reader.advance(); |
| 1010 } | 1027 } |
| 1011 recordStartOfLine(); | 1028 recordStartOfLine(); |
| 1012 } else if (next == 0xA) { | 1029 } else if (next == $lf) { |
| 1013 next = _reader.advance(); | 1030 next = _reader.advance(); |
| 1014 recordStartOfLine(); | 1031 recordStartOfLine(); |
| 1015 } else { | 1032 } else { |
| 1016 next = _reader.advance(); | 1033 next = _reader.advance(); |
| 1017 } | 1034 } |
| 1018 } | 1035 } |
| 1019 } | 1036 } |
| 1020 | 1037 |
| 1021 int _tokenizeMultiLineRawString(int quoteChar, int start) { | 1038 int _tokenizeMultiLineRawString(int quoteChar, int start) { |
| 1022 int next = _reader.advance(); | 1039 int next = _reader.advance(); |
| 1023 outer: while (next != -1) { | 1040 outer: while (next != -1) { |
| 1024 while (next != quoteChar) { | 1041 while (next != quoteChar) { |
| 1025 if (next == -1) { | 1042 if (next == -1) { |
| 1026 break outer; | 1043 break outer; |
| 1027 } else if (next == 0xD) { | 1044 } else if (next == $cr) { |
| 1028 next = _reader.advance(); | 1045 next = _reader.advance(); |
| 1029 if (next == 0xA) { | 1046 if (next == $lf) { |
| 1030 next = _reader.advance(); | 1047 next = _reader.advance(); |
| 1031 } | 1048 } |
| 1032 recordStartOfLine(); | 1049 recordStartOfLine(); |
| 1033 } else if (next == 0xA) { | 1050 } else if (next == $lf) { |
| 1034 next = _reader.advance(); | 1051 next = _reader.advance(); |
| 1035 recordStartOfLine(); | 1052 recordStartOfLine(); |
| 1036 } else { | 1053 } else { |
| 1037 next = _reader.advance(); | 1054 next = _reader.advance(); |
| 1038 } | 1055 } |
| 1039 } | 1056 } |
| 1040 next = _reader.advance(); | 1057 next = _reader.advance(); |
| 1041 if (next == quoteChar) { | 1058 if (next == quoteChar) { |
| 1042 next = _reader.advance(); | 1059 next = _reader.advance(); |
| 1043 if (next == quoteChar) { | 1060 if (next == quoteChar) { |
| 1044 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1061 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1045 return _reader.advance(); | 1062 return _reader.advance(); |
| 1046 } | 1063 } |
| 1047 } | 1064 } |
| 1048 } | 1065 } |
| 1049 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); | 1066 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); |
| 1050 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1067 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1051 return _reader.advance(); | 1068 return _reader.advance(); |
| 1052 } | 1069 } |
| 1053 | 1070 |
| 1054 int _tokenizeMultiLineString(int quoteChar, int start, bool raw) { | 1071 int _tokenizeMultiLineString(int quoteChar, int start, bool raw) { |
| 1055 if (raw) { | 1072 if (raw) { |
| 1056 return _tokenizeMultiLineRawString(quoteChar, start); | 1073 return _tokenizeMultiLineRawString(quoteChar, start); |
| 1057 } | 1074 } |
| 1058 int next = _reader.advance(); | 1075 int next = _reader.advance(); |
| 1059 while (next != -1) { | 1076 while (next != -1) { |
| 1060 if (next == 0x24) { | 1077 if (next == $$) { |
| 1061 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); | 1078 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); |
| 1062 next = _tokenizeStringInterpolation(start); | 1079 next = _tokenizeStringInterpolation(start); |
| 1063 _beginToken(); | 1080 _beginToken(); |
| 1064 start = _reader.offset; | 1081 start = _reader.offset; |
| 1065 continue; | 1082 continue; |
| 1066 } | 1083 } |
| 1067 if (next == quoteChar) { | 1084 if (next == quoteChar) { |
| 1068 next = _reader.advance(); | 1085 next = _reader.advance(); |
| 1069 if (next == quoteChar) { | 1086 if (next == quoteChar) { |
| 1070 next = _reader.advance(); | 1087 next = _reader.advance(); |
| 1071 if (next == quoteChar) { | 1088 if (next == quoteChar) { |
| 1072 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1089 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1073 return _reader.advance(); | 1090 return _reader.advance(); |
| 1074 } | 1091 } |
| 1075 } | 1092 } |
| 1076 continue; | 1093 continue; |
| 1077 } | 1094 } |
| 1078 if (next == 0x5C) { | 1095 if (next == $backslash) { |
| 1079 next = _reader.advance(); | 1096 next = _reader.advance(); |
| 1080 if (next == -1) { | 1097 if (next == -1) { |
| 1081 break; | 1098 break; |
| 1082 } | 1099 } |
| 1083 if (next == 0xD) { | 1100 if (next == $cr) { |
| 1084 next = _reader.advance(); | 1101 next = _reader.advance(); |
| 1085 if (next == 0xA) { | 1102 if (next == $lf) { |
| 1086 next = _reader.advance(); | 1103 next = _reader.advance(); |
| 1087 } | 1104 } |
| 1088 recordStartOfLine(); | 1105 recordStartOfLine(); |
| 1089 } else if (next == 0xA) { | 1106 } else if (next == $lf) { |
| 1090 recordStartOfLine(); | 1107 recordStartOfLine(); |
| 1091 next = _reader.advance(); | 1108 next = _reader.advance(); |
| 1092 } else { | 1109 } else { |
| 1093 next = _reader.advance(); | 1110 next = _reader.advance(); |
| 1094 } | 1111 } |
| 1095 } else if (next == 0xD) { | 1112 } else if (next == $cr) { |
| 1096 next = _reader.advance(); | 1113 next = _reader.advance(); |
| 1097 if (next == 0xA) { | 1114 if (next == $lf) { |
| 1098 next = _reader.advance(); | 1115 next = _reader.advance(); |
| 1099 } | 1116 } |
| 1100 recordStartOfLine(); | 1117 recordStartOfLine(); |
| 1101 } else if (next == 0xA) { | 1118 } else if (next == $lf) { |
| 1102 recordStartOfLine(); | 1119 recordStartOfLine(); |
| 1103 next = _reader.advance(); | 1120 next = _reader.advance(); |
| 1104 } else { | 1121 } else { |
| 1105 next = _reader.advance(); | 1122 next = _reader.advance(); |
| 1106 } | 1123 } |
| 1107 } | 1124 } |
| 1108 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); | 1125 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); |
| 1109 if (start == _reader.offset) { | 1126 if (start == _reader.offset) { |
| 1110 _appendStringTokenWithOffset(TokenType.STRING, "", 1); | 1127 _appendStringTokenWithOffset(TokenType.STRING, "", 1); |
| 1111 } else { | 1128 } else { |
| 1112 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1129 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1113 } | 1130 } |
| 1114 return _reader.advance(); | 1131 return _reader.advance(); |
| 1115 } | 1132 } |
| 1116 | 1133 |
| 1117 int _tokenizeMultiply(int next) => | 1134 int _tokenizeMultiply(int next) => |
| 1118 _select(0x3D, TokenType.STAR_EQ, TokenType.STAR); | 1135 _select($equal, TokenType.STAR_EQ, TokenType.STAR); |
| 1119 | 1136 |
| 1120 int _tokenizeNumber(int next) { | 1137 int _tokenizeNumber(int next) { |
| 1121 int start = _reader.offset; | 1138 int start = _reader.offset; |
| 1122 while (true) { | 1139 while (true) { |
| 1123 next = _reader.advance(); | 1140 next = _reader.advance(); |
| 1124 if (0x30 <= next && next <= 0x39) { | 1141 if ($0 <= next && next <= $9) { |
| 1125 continue; | 1142 continue; |
| 1126 } else if (next == 0x2E) { | 1143 } else if (next == $dot) { |
| 1127 return _tokenizeFractionPart(_reader.advance(), start); | 1144 return _tokenizeFractionPart(_reader.advance(), start); |
| 1128 } else if (next == 0x65 || next == 0x45) { | 1145 } else if (next == $e || next == $E) { |
| 1129 return _tokenizeFractionPart(next, start); | 1146 return _tokenizeFractionPart(next, start); |
| 1130 } else { | 1147 } else { |
| 1131 _appendStringToken( | 1148 _appendStringToken( |
| 1132 TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1)); | 1149 TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1)); |
| 1133 return next; | 1150 return next; |
| 1134 } | 1151 } |
| 1135 } | 1152 } |
| 1136 } | 1153 } |
| 1137 | 1154 |
| 1138 int _tokenizeOpenSquareBracket(int next) { | 1155 int _tokenizeOpenSquareBracket(int next) { |
| 1139 // [ [] []= | 1156 // [ [] []= |
| 1140 next = _reader.advance(); | 1157 next = _reader.advance(); |
| 1141 if (next == 0x5D) { | 1158 if (next == $close_bracket) { |
| 1142 return _select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX); | 1159 return _select($equal, TokenType.INDEX_EQ, TokenType.INDEX); |
| 1143 } else { | 1160 } else { |
| 1144 _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET); | 1161 _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET); |
| 1145 return next; | 1162 return next; |
| 1146 } | 1163 } |
| 1147 } | 1164 } |
| 1148 | 1165 |
| 1149 int _tokenizePercent(int next) => | 1166 int _tokenizePercent(int next) => |
| 1150 _select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT); | 1167 _select($equal, TokenType.PERCENT_EQ, TokenType.PERCENT); |
| 1151 | 1168 |
| 1152 int _tokenizePlus(int next) { | 1169 int _tokenizePlus(int next) { |
| 1153 // + ++ += | 1170 // + ++ += |
| 1154 next = _reader.advance(); | 1171 next = _reader.advance(); |
| 1155 if (0x2B == next) { | 1172 if ($plus == next) { |
| 1156 _appendTokenOfType(TokenType.PLUS_PLUS); | 1173 _appendTokenOfType(TokenType.PLUS_PLUS); |
| 1157 return _reader.advance(); | 1174 return _reader.advance(); |
| 1158 } else if (0x3D == next) { | 1175 } else if ($equal == next) { |
| 1159 _appendTokenOfType(TokenType.PLUS_EQ); | 1176 _appendTokenOfType(TokenType.PLUS_EQ); |
| 1160 return _reader.advance(); | 1177 return _reader.advance(); |
| 1161 } else { | 1178 } else { |
| 1162 _appendTokenOfType(TokenType.PLUS); | 1179 _appendTokenOfType(TokenType.PLUS); |
| 1163 return next; | 1180 return next; |
| 1164 } | 1181 } |
| 1165 } | 1182 } |
| 1166 | 1183 |
| 1167 int _tokenizeQuestion() { | 1184 int _tokenizeQuestion() { |
| 1168 // ? ?. ?? ??= | 1185 // ? ?. ?? ??= |
| 1169 int next = _reader.advance(); | 1186 int next = _reader.advance(); |
| 1170 if (next == 0x2E) { | 1187 if (next == $dot) { |
| 1171 // '.' | 1188 // '.' |
| 1172 _appendTokenOfType(TokenType.QUESTION_PERIOD); | 1189 _appendTokenOfType(TokenType.QUESTION_PERIOD); |
| 1173 return _reader.advance(); | 1190 return _reader.advance(); |
| 1174 } else if (next == 0x3F) { | 1191 } else if (next == $question) { |
| 1175 // '?' | 1192 // '?' |
| 1176 next = _reader.advance(); | 1193 next = _reader.advance(); |
| 1177 if (next == 0x3D) { | 1194 if (next == $equal) { |
| 1178 // '=' | 1195 // '=' |
| 1179 _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ); | 1196 _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ); |
| 1180 return _reader.advance(); | 1197 return _reader.advance(); |
| 1181 } else { | 1198 } else { |
| 1182 _appendTokenOfType(TokenType.QUESTION_QUESTION); | 1199 _appendTokenOfType(TokenType.QUESTION_QUESTION); |
| 1183 return next; | 1200 return next; |
| 1184 } | 1201 } |
| 1185 } else { | 1202 } else { |
| 1186 _appendTokenOfType(TokenType.QUESTION); | 1203 _appendTokenOfType(TokenType.QUESTION); |
| 1187 return next; | 1204 return next; |
| 1188 } | 1205 } |
| 1189 } | 1206 } |
| 1190 | 1207 |
| 1191 int _tokenizeSingleLineComment(int next) { | 1208 int _tokenizeSingleLineComment(int next) { |
| 1192 while (true) { | 1209 while (true) { |
| 1193 next = _reader.advance(); | 1210 next = _reader.advance(); |
| 1194 if (-1 == next) { | 1211 if (-1 == next) { |
| 1195 _appendCommentToken( | 1212 _appendCommentToken( |
| 1196 TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0)); | 1213 TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0)); |
| 1197 return next; | 1214 return next; |
| 1198 } else if (0xA == next || 0xD == next) { | 1215 } else if ($lf == next || $cr == next) { |
| 1199 _appendCommentToken( | 1216 _appendCommentToken( |
| 1200 TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1)); | 1217 TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1)); |
| 1201 return next; | 1218 return next; |
| 1202 } | 1219 } |
| 1203 } | 1220 } |
| 1204 } | 1221 } |
| 1205 | 1222 |
| 1206 int _tokenizeSingleLineRawString(int next, int quoteChar, int start) { | 1223 int _tokenizeSingleLineRawString(int next, int quoteChar, int start) { |
| 1207 next = _reader.advance(); | 1224 next = _reader.advance(); |
| 1208 while (next != -1) { | 1225 while (next != -1) { |
| 1209 if (next == quoteChar) { | 1226 if (next == quoteChar) { |
| 1210 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1227 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1211 return _reader.advance(); | 1228 return _reader.advance(); |
| 1212 } else if (next == 0xD || next == 0xA) { | 1229 } else if (next == $cr || next == $lf) { |
| 1213 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); | 1230 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); |
| 1214 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); | 1231 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); |
| 1215 return _reader.advance(); | 1232 return _reader.advance(); |
| 1216 } | 1233 } |
| 1217 next = _reader.advance(); | 1234 next = _reader.advance(); |
| 1218 } | 1235 } |
| 1219 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); | 1236 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); |
| 1220 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1237 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1221 return _reader.advance(); | 1238 return _reader.advance(); |
| 1222 } | 1239 } |
| 1223 | 1240 |
| 1224 int _tokenizeSingleLineString(int next, int quoteChar, int start) { | 1241 int _tokenizeSingleLineString(int next, int quoteChar, int start) { |
| 1225 while (next != quoteChar) { | 1242 while (next != quoteChar) { |
| 1226 if (next == 0x5C) { | 1243 if (next == $backslash) { |
| 1227 next = _reader.advance(); | 1244 next = _reader.advance(); |
| 1228 } else if (next == 0x24) { | 1245 } else if (next == $$) { |
| 1229 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); | 1246 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); |
| 1230 next = _tokenizeStringInterpolation(start); | 1247 next = _tokenizeStringInterpolation(start); |
| 1231 _beginToken(); | 1248 _beginToken(); |
| 1232 start = _reader.offset; | 1249 start = _reader.offset; |
| 1233 continue; | 1250 continue; |
| 1234 } | 1251 } |
| 1235 if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) { | 1252 if (next <= $cr && (next == $lf || next == $cr || next == -1)) { |
| 1236 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); | 1253 _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL); |
| 1237 if (start == _reader.offset) { | 1254 if (start == _reader.offset) { |
| 1238 _appendStringTokenWithOffset(TokenType.STRING, "", 1); | 1255 _appendStringTokenWithOffset(TokenType.STRING, "", 1); |
| 1239 } else if (next == -1) { | 1256 } else if (next == -1) { |
| 1240 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1257 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1241 } else { | 1258 } else { |
| 1242 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); | 1259 _appendStringToken(TokenType.STRING, _reader.getString(start, -1)); |
| 1243 } | 1260 } |
| 1244 return _reader.advance(); | 1261 return _reader.advance(); |
| 1245 } | 1262 } |
| 1246 next = _reader.advance(); | 1263 next = _reader.advance(); |
| 1247 } | 1264 } |
| 1248 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); | 1265 _appendStringToken(TokenType.STRING, _reader.getString(start, 0)); |
| 1249 return _reader.advance(); | 1266 return _reader.advance(); |
| 1250 } | 1267 } |
| 1251 | 1268 |
| 1252 int _tokenizeSlashOrComment(int next) { | 1269 int _tokenizeSlashOrComment(int next) { |
| 1253 next = _reader.advance(); | 1270 next = _reader.advance(); |
| 1254 if (0x2A == next) { | 1271 if ($asterisk == next) { |
| 1255 return _tokenizeMultiLineComment(next); | 1272 return _tokenizeMultiLineComment(next); |
| 1256 } else if (0x2F == next) { | 1273 } else if ($slash == next) { |
| 1257 return _tokenizeSingleLineComment(next); | 1274 return _tokenizeSingleLineComment(next); |
| 1258 } else if (0x3D == next) { | 1275 } else if ($equal == next) { |
| 1259 _appendTokenOfType(TokenType.SLASH_EQ); | 1276 _appendTokenOfType(TokenType.SLASH_EQ); |
| 1260 return _reader.advance(); | 1277 return _reader.advance(); |
| 1261 } else { | 1278 } else { |
| 1262 _appendTokenOfType(TokenType.SLASH); | 1279 _appendTokenOfType(TokenType.SLASH); |
| 1263 return next; | 1280 return next; |
| 1264 } | 1281 } |
| 1265 } | 1282 } |
| 1266 | 1283 |
| 1267 int _tokenizeString(int next, int start, bool raw) { | 1284 int _tokenizeString(int next, int start, bool raw) { |
| 1268 int quoteChar = next; | 1285 int quoteChar = next; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1281 if (raw) { | 1298 if (raw) { |
| 1282 return _tokenizeSingleLineRawString(next, quoteChar, start); | 1299 return _tokenizeSingleLineRawString(next, quoteChar, start); |
| 1283 } else { | 1300 } else { |
| 1284 return _tokenizeSingleLineString(next, quoteChar, start); | 1301 return _tokenizeSingleLineString(next, quoteChar, start); |
| 1285 } | 1302 } |
| 1286 } | 1303 } |
| 1287 | 1304 |
| 1288 int _tokenizeStringInterpolation(int start) { | 1305 int _tokenizeStringInterpolation(int start) { |
| 1289 _beginToken(); | 1306 _beginToken(); |
| 1290 int next = _reader.advance(); | 1307 int next = _reader.advance(); |
| 1291 if (next == 0x7B) { | 1308 if (next == $lbrace) { |
| 1292 return _tokenizeInterpolatedExpression(next, start); | 1309 return _tokenizeInterpolatedExpression(next, start); |
| 1293 } else { | 1310 } else { |
| 1294 return _tokenizeInterpolatedIdentifier(next, start); | 1311 return _tokenizeInterpolatedIdentifier(next, start); |
| 1295 } | 1312 } |
| 1296 } | 1313 } |
| 1297 | 1314 |
| 1298 int _tokenizeTag(int next) { | 1315 int _tokenizeTag(int next) { |
| 1299 // # or #!.*[\n\r] | 1316 // # or #!.*[\n\r] |
| 1300 if (_reader.offset == 0) { | 1317 if (_reader.offset == 0) { |
| 1301 if (_reader.peek() == 0x21) { | 1318 if (_reader.peek() == $exclamation) { |
| 1302 do { | 1319 do { |
| 1303 next = _reader.advance(); | 1320 next = _reader.advance(); |
| 1304 } while (next != 0xA && next != 0xD && next > 0); | 1321 } while (next != $lf && next != $cr && next > 0); |
| 1305 _appendStringToken( | 1322 _appendStringToken( |
| 1306 TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0)); | 1323 TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0)); |
| 1307 return next; | 1324 return next; |
| 1308 } | 1325 } |
| 1309 } | 1326 } |
| 1310 _appendTokenOfType(TokenType.HASH); | 1327 _appendTokenOfType(TokenType.HASH); |
| 1311 return _reader.advance(); | 1328 return _reader.advance(); |
| 1312 } | 1329 } |
| 1313 | 1330 |
| 1314 int _tokenizeTilde(int next) { | 1331 int _tokenizeTilde(int next) { |
| 1315 // ~ ~/ ~/= | 1332 // ~ ~/ ~/= |
| 1316 next = _reader.advance(); | 1333 next = _reader.advance(); |
| 1317 if (next == 0x2F) { | 1334 if (next == $slash) { |
| 1318 return _select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH); | 1335 return _select($equal, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH); |
| 1319 } else { | 1336 } else { |
| 1320 _appendTokenOfType(TokenType.TILDE); | 1337 _appendTokenOfType(TokenType.TILDE); |
| 1321 return next; | 1338 return next; |
| 1322 } | 1339 } |
| 1323 } | 1340 } |
| 1324 | 1341 |
| 1325 /** | 1342 /** |
| 1326 * Checks if [value] is a single-line or multi-line comment. | 1343 * Checks if [value] is a single-line or multi-line comment. |
| 1327 */ | 1344 */ |
| 1328 static bool _isDocumentationComment(String value) { | 1345 static bool _isDocumentationComment(String value) { |
| 1329 return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) || | 1346 return StringUtilities.startsWith3(value, 0, $slash, $slash, $slash) || |
| 1330 StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A); | 1347 StringUtilities.startsWith3(value, 0, $slash, $asterisk, $asterisk); |
| 1331 } | 1348 } |
| 1332 } | 1349 } |
| 1333 | 1350 |
| 1334 /** | 1351 /** |
| 1335 * The error codes used for errors detected by the scanner. | 1352 * The error codes used for errors detected by the scanner. |
| 1336 */ | 1353 */ |
| 1337 class ScannerErrorCode extends ErrorCode { | 1354 class ScannerErrorCode extends ErrorCode { |
| 1338 static const ScannerErrorCode ILLEGAL_CHARACTER = | 1355 static const ScannerErrorCode ILLEGAL_CHARACTER = |
| 1339 const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}"); | 1356 const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}"); |
| 1340 | 1357 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1366 */ | 1383 */ |
| 1367 const ScannerErrorCode(String name, String message, [String correction]) | 1384 const ScannerErrorCode(String name, String message, [String correction]) |
| 1368 : super(name, message, correction); | 1385 : super(name, message, correction); |
| 1369 | 1386 |
| 1370 @override | 1387 @override |
| 1371 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; | 1388 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; |
| 1372 | 1389 |
| 1373 @override | 1390 @override |
| 1374 ErrorType get type => ErrorType.SYNTACTIC_ERROR; | 1391 ErrorType get type => ErrorType.SYNTACTIC_ERROR; |
| 1375 } | 1392 } |
| OLD | NEW |