| 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 engine.scanner; | 5 library engine.scanner; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'error.dart'; | 9 import 'error.dart'; |
| 10 import 'java_engine.dart'; | 10 import 'java_engine.dart'; |
| 11 import 'source.dart'; | 11 import 'source.dart'; |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * A `BeginToken` is the opening half of a grouping pair of tokens. This is used | 14 * The opening half of a grouping pair of tokens. This is used for curly |
| 15 * for curly brackets ('{'), parentheses ('('), and square brackets ('['). | 15 * brackets ('{'), parentheses ('('), and square brackets ('['). |
| 16 */ | 16 */ |
| 17 class BeginToken extends Token { | 17 class BeginToken extends Token { |
| 18 /** | 18 /** |
| 19 * The token that corresponds to this token. | 19 * The token that corresponds to this token. |
| 20 */ | 20 */ |
| 21 Token endToken; | 21 Token endToken; |
| 22 | 22 |
| 23 /** | 23 /** |
| 24 * Initialize a newly created token to have the given [type] at the given | 24 * Initialize a newly created token to have the given [type] at the given |
| 25 * [offset]. | 25 * [offset]. |
| 26 */ | 26 */ |
| 27 BeginToken(TokenType type, int offset) : super(type, offset) { | 27 BeginToken(TokenType type, int offset) : super(type, offset) { |
| 28 assert(type == TokenType.OPEN_CURLY_BRACKET || | 28 assert(type == TokenType.OPEN_CURLY_BRACKET || |
| 29 type == TokenType.OPEN_PAREN || | 29 type == TokenType.OPEN_PAREN || |
| 30 type == TokenType.OPEN_SQUARE_BRACKET || | 30 type == TokenType.OPEN_SQUARE_BRACKET || |
| 31 type == TokenType.STRING_INTERPOLATION_EXPRESSION); | 31 type == TokenType.STRING_INTERPOLATION_EXPRESSION); |
| 32 } | 32 } |
| 33 | 33 |
| 34 @override | 34 @override |
| 35 Token copy() => new BeginToken(type, offset); | 35 Token copy() => new BeginToken(type, offset); |
| 36 } | 36 } |
| 37 | 37 |
| 38 /** | 38 /** |
| 39 * A `BeginTokenWithComment` is a begin token that is preceded by comments. | 39 * A begin token that is preceded by comments. |
| 40 */ | 40 */ |
| 41 class BeginTokenWithComment extends BeginToken { | 41 class BeginTokenWithComment extends BeginToken { |
| 42 /** | 42 /** |
| 43 * The first comment in the list of comments that precede this token. | 43 * The first comment in the list of comments that precede this token. |
| 44 */ | 44 */ |
| 45 CommentToken _precedingComment; | 45 CommentToken _precedingComment; |
| 46 | 46 |
| 47 /** | 47 /** |
| 48 * Initialize a newly created token to have the given [type] at the given | 48 * Initialize a newly created token to have the given [type] at the given |
| 49 * [offset] and to be preceded by the comments reachable from the given | 49 * [offset] and to be preceded by the comments reachable from the given |
| (...skipping 20 matching lines...) Expand all Loading... |
| 70 token = token.next; | 70 token = token.next; |
| 71 } | 71 } |
| 72 } | 72 } |
| 73 | 73 |
| 74 @override | 74 @override |
| 75 Token copy() => | 75 Token copy() => |
| 76 new BeginTokenWithComment(type, offset, copyComments(precedingComments)); | 76 new BeginTokenWithComment(type, offset, copyComments(precedingComments)); |
| 77 } | 77 } |
| 78 | 78 |
| 79 /** | 79 /** |
| 80 * A `CharacterRangeReader` is a [CharacterReader] that reads a range of | 80 * A [CharacterReader] that reads a range of characters from another character |
| 81 * characters from another character reader. | 81 * reader. |
| 82 */ | 82 */ |
| 83 class CharacterRangeReader extends CharacterReader { | 83 class CharacterRangeReader extends CharacterReader { |
| 84 /** | 84 /** |
| 85 * The reader from which the characters are actually being read. | 85 * The reader from which the characters are actually being read. |
| 86 */ | 86 */ |
| 87 final CharacterReader baseReader; | 87 final CharacterReader baseReader; |
| 88 | 88 |
| 89 /** | 89 /** |
| 90 * The last character to be read. | 90 * The last character to be read. |
| 91 */ | 91 */ |
| (...skipping 30 matching lines...) Expand all Loading... |
| 122 @override | 122 @override |
| 123 int peek() { | 123 int peek() { |
| 124 if (baseReader.offset + 1 >= endIndex) { | 124 if (baseReader.offset + 1 >= endIndex) { |
| 125 return -1; | 125 return -1; |
| 126 } | 126 } |
| 127 return baseReader.peek(); | 127 return baseReader.peek(); |
| 128 } | 128 } |
| 129 } | 129 } |
| 130 | 130 |
| 131 /** | 131 /** |
| 132 * A `CharacterReader` is used by the scanner to read the characters to be | 132 * An object used by the scanner to read the characters to be scanned. |
| 133 * scanned. | |
| 134 */ | 133 */ |
| 135 abstract class CharacterReader { | 134 abstract class CharacterReader { |
| 136 /** | 135 /** |
| 137 * The current offset relative to the beginning of the source. Return the | 136 * The current offset relative to the beginning of the source. Return the |
| 138 * initial offset if the scanner has not yet scanned the source code, and one | 137 * initial offset if the scanner has not yet scanned the source code, and one |
| 139 * (1) past the end of the source code if the entire source code has been | 138 * (1) past the end of the source code if the entire source code has been |
| 140 * scanned. | 139 * scanned. |
| 141 */ | 140 */ |
| 142 int get offset; | 141 int get offset; |
| 143 | 142 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 164 String getString(int start, int endDelta); | 163 String getString(int start, int endDelta); |
| 165 | 164 |
| 166 /** | 165 /** |
| 167 * Return the character at the current position without changing the current | 166 * Return the character at the current position without changing the current |
| 168 * position. | 167 * position. |
| 169 */ | 168 */ |
| 170 int peek(); | 169 int peek(); |
| 171 } | 170 } |
| 172 | 171 |
| 173 /** | 172 /** |
| 174 * A `CharSequenceReader` is a [CharacterReader] that reads characters from a | 173 * A [CharacterReader] that reads characters from a character sequence. |
| 175 * character sequence. | |
| 176 */ | 174 */ |
| 177 class CharSequenceReader implements CharacterReader { | 175 class CharSequenceReader implements CharacterReader { |
| 178 /** | 176 /** |
| 179 * The sequence from which characters will be read. | 177 * The sequence from which characters will be read. |
| 180 */ | 178 */ |
| 181 final String _sequence; | 179 final String _sequence; |
| 182 | 180 |
| 183 /** | 181 /** |
| 184 * The number of characters in the string. | 182 * The number of characters in the string. |
| 185 */ | 183 */ |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 @override | 220 @override |
| 223 int peek() { | 221 int peek() { |
| 224 if (_charOffset + 1 >= _stringLength) { | 222 if (_charOffset + 1 >= _stringLength) { |
| 225 return -1; | 223 return -1; |
| 226 } | 224 } |
| 227 return _sequence.codeUnitAt(_charOffset + 1); | 225 return _sequence.codeUnitAt(_charOffset + 1); |
| 228 } | 226 } |
| 229 } | 227 } |
| 230 | 228 |
| 231 /** | 229 /** |
| 232 * A `CommentToken` is a token representing a comment. | 230 * A token representing a comment. |
| 233 */ | 231 */ |
| 234 class CommentToken extends StringToken { | 232 class CommentToken extends StringToken { |
| 235 /** | 233 /** |
| 236 * The [Token] that contains this comment. | 234 * The [Token] that contains this comment. |
| 237 */ | 235 */ |
| 238 Token parent; | 236 Token parent; |
| 239 | 237 |
| 240 /** | 238 /** |
| 241 * Initialize a newly created token to represent a token of the given [type] | 239 * Initialize a newly created token to represent a token of the given [type] |
| 242 * with the given [value] at the given [offset]. | 240 * with the given [value] at the given [offset]. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 264 * with the given [value] at the given [offset]. | 262 * with the given [value] at the given [offset]. |
| 265 */ | 263 */ |
| 266 DocumentationCommentToken(TokenType type, String value, int offset) | 264 DocumentationCommentToken(TokenType type, String value, int offset) |
| 267 : super(type, value, offset); | 265 : super(type, value, offset); |
| 268 | 266 |
| 269 @override | 267 @override |
| 270 CommentToken copy() => new DocumentationCommentToken(type, _value, offset); | 268 CommentToken copy() => new DocumentationCommentToken(type, _value, offset); |
| 271 } | 269 } |
| 272 | 270 |
| 273 /** | 271 /** |
| 274 * The enumeration `Keyword` defines the keywords in the Dart programming | 272 * The keywords in the Dart programming language. |
| 275 * language. | |
| 276 */ | 273 */ |
| 277 class Keyword { | 274 class Keyword { |
| 278 static const Keyword ASSERT = const Keyword('ASSERT', "assert"); | 275 static const Keyword ASSERT = const Keyword('ASSERT', "assert"); |
| 279 | 276 |
| 280 static const Keyword BREAK = const Keyword('BREAK', "break"); | 277 static const Keyword BREAK = const Keyword('BREAK', "break"); |
| 281 | 278 |
| 282 static const Keyword CASE = const Keyword('CASE', "case"); | 279 static const Keyword CASE = const Keyword('CASE', "case"); |
| 283 | 280 |
| 284 static const Keyword CATCH = const Keyword('CATCH', "catch"); | 281 static const Keyword CATCH = const Keyword('CATCH', "catch"); |
| 285 | 282 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 LinkedHashMap<String, Keyword> result = | 461 LinkedHashMap<String, Keyword> result = |
| 465 new LinkedHashMap<String, Keyword>(); | 462 new LinkedHashMap<String, Keyword>(); |
| 466 for (Keyword keyword in values) { | 463 for (Keyword keyword in values) { |
| 467 result[keyword.syntax] = keyword; | 464 result[keyword.syntax] = keyword; |
| 468 } | 465 } |
| 469 return result; | 466 return result; |
| 470 } | 467 } |
| 471 } | 468 } |
| 472 | 469 |
| 473 /** | 470 /** |
| 474 * A `KeywordState` is a state in a state machine used to scan keywords. | 471 * A state in a state machine used to scan keywords. |
| 475 */ | 472 */ |
| 476 class KeywordState { | 473 class KeywordState { |
| 477 /** | 474 /** |
| 478 * An empty transition table used by leaf states. | 475 * An empty transition table used by leaf states. |
| 479 */ | 476 */ |
| 480 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26); | 477 static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26); |
| 481 | 478 |
| 482 /** | 479 /** |
| 483 * The initial state in the state machine. | 480 * The initial state in the state machine. |
| 484 */ | 481 */ |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 * [character], or `null` if there is no valid state reachable from this state | 513 * [character], or `null` if there is no valid state reachable from this state |
| 517 * with such a transition. | 514 * with such a transition. |
| 518 */ | 515 */ |
| 519 KeywordState next(int character) => _table[character - 0x61]; | 516 KeywordState next(int character) => _table[character - 0x61]; |
| 520 | 517 |
| 521 /** | 518 /** |
| 522 * Create the next state in the state machine where we have already recognized | 519 * Create the next state in the state machine where we have already recognized |
| 523 * the subset of strings in the given array of [strings] starting at the given | 520 * the subset of strings in the given array of [strings] starting at the given |
| 524 * [offset] and having the given [length]. All of these strings have a common | 521 * [offset] and having the given [length]. All of these strings have a common |
| 525 * prefix and the next character is at the given [start] index. | 522 * prefix and the next character is at the given [start] index. |
| 526 * | |
| 527 * [start] the index of the character in the strings used to transition to a | |
| 528 * new state | |
| 529 * [strings] an array containing all of the strings that will be recognized by | |
| 530 * the state machine | |
| 531 * [offset] the offset of the first string in the array that has the prefix | |
| 532 * that is assumed to have been recognized by the time we reach the state | |
| 533 * being built | |
| 534 * [length] the number of strings in the array that pass through the state | |
| 535 * being built | |
| 536 */ | 523 */ |
| 537 static KeywordState _computeKeywordStateTable( | 524 static KeywordState _computeKeywordStateTable( |
| 538 int start, List<String> strings, int offset, int length) { | 525 int start, List<String> strings, int offset, int length) { |
| 539 List<KeywordState> result = new List<KeywordState>(26); | 526 List<KeywordState> result = new List<KeywordState>(26); |
| 540 assert(length != 0); | 527 assert(length != 0); |
| 541 int chunk = 0x0; | 528 int chunk = 0x0; |
| 542 int chunkStart = -1; | 529 int chunkStart = -1; |
| 543 bool isLeaf = false; | 530 bool isLeaf = false; |
| 544 for (int i = offset; i < offset + length; i++) { | 531 for (int i = offset; i < offset + length; i++) { |
| 545 if (strings[i].length == start) { | 532 if (strings[i].length == start) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 List<String> strings = new List<String>(values.length); | 567 List<String> strings = new List<String>(values.length); |
| 581 for (int i = 0; i < values.length; i++) { | 568 for (int i = 0; i < values.length; i++) { |
| 582 strings[i] = values[i].syntax; | 569 strings[i] = values[i].syntax; |
| 583 } | 570 } |
| 584 strings.sort(); | 571 strings.sort(); |
| 585 return _computeKeywordStateTable(0, strings, 0, strings.length); | 572 return _computeKeywordStateTable(0, strings, 0, strings.length); |
| 586 } | 573 } |
| 587 } | 574 } |
| 588 | 575 |
| 589 /** | 576 /** |
| 590 * A `KeywordToken` is a keyword in the language. | 577 * A token representing a keyword in the language. |
| 591 */ | 578 */ |
| 592 class KeywordToken extends Token { | 579 class KeywordToken extends Token { |
| 593 /** | 580 /** |
| 594 * The keyword being represented by this token. | 581 * The keyword being represented by this token. |
| 595 */ | 582 */ |
| 596 final Keyword keyword; | 583 final Keyword keyword; |
| 597 | 584 |
| 598 /** | 585 /** |
| 599 * Initialize a newly created token to represent the given [keyword] at the | 586 * Initialize a newly created token to represent the given [keyword] at the |
| 600 * given [offset]. | 587 * given [offset]. |
| 601 */ | 588 */ |
| 602 KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset); | 589 KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset); |
| 603 | 590 |
| 604 @override | 591 @override |
| 605 String get lexeme => keyword.syntax; | 592 String get lexeme => keyword.syntax; |
| 606 | 593 |
| 607 @override | 594 @override |
| 608 Token copy() => new KeywordToken(keyword, offset); | 595 Token copy() => new KeywordToken(keyword, offset); |
| 609 | 596 |
| 610 @override | 597 @override |
| 611 Keyword value() => keyword; | 598 Keyword value() => keyword; |
| 612 } | 599 } |
| 613 | 600 |
| 614 /** | 601 /** |
| 615 * A `KeywordTokenWithComment` is a keyword token that is preceded by comments. | 602 * A keyword token that is preceded by comments. |
| 616 */ | 603 */ |
| 617 class KeywordTokenWithComment extends KeywordToken { | 604 class KeywordTokenWithComment extends KeywordToken { |
| 618 /** | 605 /** |
| 619 * The first comment in the list of comments that precede this token. | 606 * The first comment in the list of comments that precede this token. |
| 620 */ | 607 */ |
| 621 CommentToken _precedingComment; | 608 CommentToken _precedingComment; |
| 622 | 609 |
| 623 /** | 610 /** |
| 624 * Initialize a newly created token to to represent the given [keyword] at the | 611 * Initialize a newly created token to to represent the given [keyword] at the |
| 625 * given [offset] and to be preceded by the comments reachable from the given | 612 * given [offset] and to be preceded by the comments reachable from the given |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 | 919 |
| 933 /** | 920 /** |
| 934 * Record the fact that we are at the beginning of a new line in the source. | 921 * Record the fact that we are at the beginning of a new line in the source. |
| 935 */ | 922 */ |
| 936 void recordStartOfLine() { | 923 void recordStartOfLine() { |
| 937 _lineStarts.add(_reader.offset); | 924 _lineStarts.add(_reader.offset); |
| 938 } | 925 } |
| 939 | 926 |
| 940 /** | 927 /** |
| 941 * Record that the source begins on the given [line] and [column] at the | 928 * Record that the source begins on the given [line] and [column] at the |
| 942 * current offset as given by the reader. The line starts for lines before the | 929 * current offset as given by the reader. Both the line and the column are |
| 943 * given line will not be correct. | 930 * one-based indexes. The line starts for lines before the given line will not |
| 931 * be correct. |
| 944 * | 932 * |
| 945 * This method must be invoked at most one time and must be invoked before | 933 * This method must be invoked at most one time and must be invoked before |
| 946 * scanning begins. The values provided must be sensible. The results are | 934 * scanning begins. The values provided must be sensible. The results are |
| 947 * undefined if these conditions are violated. | 935 * undefined if these conditions are violated. |
| 948 * | |
| 949 * [line] the one-based index of the line containing the first character of | |
| 950 * the source | |
| 951 * [column] the one-based index of the column in which the first character of | |
| 952 * the source occurs | |
| 953 */ | 936 */ |
| 954 void setSourceStart(int line, int column) { | 937 void setSourceStart(int line, int column) { |
| 955 int offset = _reader.offset; | 938 int offset = _reader.offset; |
| 956 if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) { | 939 if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) { |
| 957 return; | 940 return; |
| 958 } | 941 } |
| 959 for (int i = 2; i < line; i++) { | 942 for (int i = 2; i < line; i++) { |
| 960 _lineStarts.add(1); | 943 _lineStarts.add(1); |
| 961 } | 944 } |
| 962 _lineStarts.add(offset - column + 1); | 945 _lineStarts.add(offset - column + 1); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1123 } | 1106 } |
| 1124 // | 1107 // |
| 1125 // We should never get to this point because we wouldn't be inside a string | 1108 // We should never get to this point because we wouldn't be inside a string |
| 1126 // interpolation expression unless we had previously found the start of the | 1109 // interpolation expression unless we had previously found the start of the |
| 1127 // expression. | 1110 // expression. |
| 1128 // | 1111 // |
| 1129 return null; | 1112 return null; |
| 1130 } | 1113 } |
| 1131 | 1114 |
| 1132 /** | 1115 /** |
| 1133 * Report an error at the current offset. | 1116 * Report an error at the current offset. The [errorCode] is the error code |
| 1134 * | 1117 * indicating the nature of the error. The [arguments] are any arguments |
| 1135 * [errorCode] the error code indicating the nature of the error | 1118 * needed to complete the error message |
| 1136 * [arguments] any arguments needed to complete the error message | |
| 1137 */ | 1119 */ |
| 1138 void _reportError(ScannerErrorCode errorCode, [List<Object> arguments]) { | 1120 void _reportError(ScannerErrorCode errorCode, [List<Object> arguments]) { |
| 1139 _errorListener.onError(new AnalysisError.con2( | 1121 _errorListener.onError(new AnalysisError.con2( |
| 1140 source, _reader.offset, 1, errorCode, arguments)); | 1122 source, _reader.offset, 1, errorCode, arguments)); |
| 1141 } | 1123 } |
| 1142 | 1124 |
| 1143 int _select(int choice, TokenType yesType, TokenType noType) { | 1125 int _select(int choice, TokenType yesType, TokenType noType) { |
| 1144 int next = _reader.advance(); | 1126 int next = _reader.advance(); |
| 1145 if (next == choice) { | 1127 if (next == choice) { |
| 1146 _appendTokenOfType(yesType); | 1128 _appendTokenOfType(yesType); |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1770 /** | 1752 /** |
| 1771 * Checks if [value] is a single-line or multi-line comment. | 1753 * Checks if [value] is a single-line or multi-line comment. |
| 1772 */ | 1754 */ |
| 1773 static bool _isDocumentationComment(String value) { | 1755 static bool _isDocumentationComment(String value) { |
| 1774 return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) || | 1756 return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) || |
| 1775 StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A); | 1757 StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A); |
| 1776 } | 1758 } |
| 1777 } | 1759 } |
| 1778 | 1760 |
| 1779 /** | 1761 /** |
| 1780 * The enumeration `ScannerErrorCode` defines the error codes used for errors | 1762 * The error codes used for errors detected by the scanner. |
| 1781 * detected by the scanner. | |
| 1782 */ | 1763 */ |
| 1783 class ScannerErrorCode extends ErrorCode { | 1764 class ScannerErrorCode extends ErrorCode { |
| 1784 static const ScannerErrorCode ILLEGAL_CHARACTER = | 1765 static const ScannerErrorCode ILLEGAL_CHARACTER = |
| 1785 const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}"); | 1766 const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}"); |
| 1786 | 1767 |
| 1787 static const ScannerErrorCode MISSING_DIGIT = | 1768 static const ScannerErrorCode MISSING_DIGIT = |
| 1788 const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected"); | 1769 const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected"); |
| 1789 | 1770 |
| 1790 static const ScannerErrorCode MISSING_HEX_DIGIT = | 1771 static const ScannerErrorCode MISSING_HEX_DIGIT = |
| 1791 const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected"); | 1772 const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected"); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1814 : super(name, message, correction); | 1795 : super(name, message, correction); |
| 1815 | 1796 |
| 1816 @override | 1797 @override |
| 1817 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; | 1798 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; |
| 1818 | 1799 |
| 1819 @override | 1800 @override |
| 1820 ErrorType get type => ErrorType.SYNTACTIC_ERROR; | 1801 ErrorType get type => ErrorType.SYNTACTIC_ERROR; |
| 1821 } | 1802 } |
| 1822 | 1803 |
| 1823 /** | 1804 /** |
| 1824 * A `StringToken` is a token whose value is independent of it's type. | 1805 * A token whose value is independent of it's type. |
| 1825 */ | 1806 */ |
| 1826 class StringToken extends Token { | 1807 class StringToken extends Token { |
| 1827 /** | 1808 /** |
| 1828 * The lexeme represented by this token. | 1809 * The lexeme represented by this token. |
| 1829 */ | 1810 */ |
| 1830 String _value; | 1811 String _value; |
| 1831 | 1812 |
| 1832 /** | 1813 /** |
| 1833 * Initialize a newly created token to represent a token of the given [type] | 1814 * Initialize a newly created token to represent a token of the given [type] |
| 1834 * with the given [value] at the given [offset]. | 1815 * with the given [value] at the given [offset]. |
| 1835 */ | 1816 */ |
| 1836 StringToken(TokenType type, String value, int offset) : super(type, offset) { | 1817 StringToken(TokenType type, String value, int offset) : super(type, offset) { |
| 1837 this._value = StringUtilities.intern(value); | 1818 this._value = StringUtilities.intern(value); |
| 1838 } | 1819 } |
| 1839 | 1820 |
| 1840 @override | 1821 @override |
| 1841 String get lexeme => _value; | 1822 String get lexeme => _value; |
| 1842 | 1823 |
| 1843 @override | 1824 @override |
| 1844 Token copy() => new StringToken(type, _value, offset); | 1825 Token copy() => new StringToken(type, _value, offset); |
| 1845 | 1826 |
| 1846 @override | 1827 @override |
| 1847 String value() => _value; | 1828 String value() => _value; |
| 1848 } | 1829 } |
| 1849 | 1830 |
| 1850 /** | 1831 /** |
| 1851 * A `StringTokenWithComment` is a string token that is preceded by comments. | 1832 * A string token that is preceded by comments. |
| 1852 */ | 1833 */ |
| 1853 class StringTokenWithComment extends StringToken { | 1834 class StringTokenWithComment extends StringToken { |
| 1854 /** | 1835 /** |
| 1855 * The first comment in the list of comments that precede this token. | 1836 * The first comment in the list of comments that precede this token. |
| 1856 */ | 1837 */ |
| 1857 CommentToken _precedingComment; | 1838 CommentToken _precedingComment; |
| 1858 | 1839 |
| 1859 /** | 1840 /** |
| 1860 * Initialize a newly created token to have the given [type] at the given | 1841 * Initialize a newly created token to have the given [type] at the given |
| 1861 * [offset] and to be preceded by the comments reachable from the given | 1842 * [offset] and to be preceded by the comments reachable from the given |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1883 token = token.next; | 1864 token = token.next; |
| 1884 } | 1865 } |
| 1885 } | 1866 } |
| 1886 | 1867 |
| 1887 @override | 1868 @override |
| 1888 Token copy() => new StringTokenWithComment( | 1869 Token copy() => new StringTokenWithComment( |
| 1889 type, lexeme, offset, copyComments(precedingComments)); | 1870 type, lexeme, offset, copyComments(precedingComments)); |
| 1890 } | 1871 } |
| 1891 | 1872 |
| 1892 /** | 1873 /** |
| 1893 * A `SubSequenceReader` is a [CharacterReader] that reads characters from a | 1874 * A [CharacterReader] that reads characters from a character sequence, but adds |
| 1894 * character sequence, but adds a delta when reporting the current character | 1875 * a delta when reporting the current character offset so that the character |
| 1895 * offset so that the character sequence can be a subsequence from a larger | 1876 * sequence can be a subsequence from a larger sequence. |
| 1896 * sequence. | |
| 1897 */ | 1877 */ |
| 1898 class SubSequenceReader extends CharSequenceReader { | 1878 class SubSequenceReader extends CharSequenceReader { |
| 1899 /** | 1879 /** |
| 1900 * The offset from the beginning of the file to the beginning of the source | 1880 * The offset from the beginning of the file to the beginning of the source |
| 1901 * being scanned. | 1881 * being scanned. |
| 1902 */ | 1882 */ |
| 1903 final int _offsetDelta; | 1883 final int _offsetDelta; |
| 1904 | 1884 |
| 1905 /** | 1885 /** |
| 1906 * Initialize a newly created reader to read the characters in the given | 1886 * Initialize a newly created reader to read the characters in the given |
| 1907 * [sequence]. The [_offsetDelta] is the offset from the beginning of the file | 1887 * [sequence]. The [_offsetDelta] is the offset from the beginning of the file |
| 1908 * to the beginning of the source being scanned | 1888 * to the beginning of the source being scanned |
| 1909 */ | 1889 */ |
| 1910 SubSequenceReader(String sequence, this._offsetDelta) : super(sequence); | 1890 SubSequenceReader(String sequence, this._offsetDelta) : super(sequence); |
| 1911 | 1891 |
| 1912 @override | 1892 @override |
| 1913 int get offset => _offsetDelta + super.offset; | 1893 int get offset => _offsetDelta + super.offset; |
| 1914 | 1894 |
| 1915 @override | 1895 @override |
| 1916 void set offset(int offset) { | 1896 void set offset(int offset) { |
| 1917 super.offset = offset - _offsetDelta; | 1897 super.offset = offset - _offsetDelta; |
| 1918 } | 1898 } |
| 1919 | 1899 |
| 1920 @override | 1900 @override |
| 1921 String getString(int start, int endDelta) => | 1901 String getString(int start, int endDelta) => |
| 1922 super.getString(start - _offsetDelta, endDelta); | 1902 super.getString(start - _offsetDelta, endDelta); |
| 1923 } | 1903 } |
| 1924 | 1904 |
| 1925 /** | 1905 /** |
| 1926 * A `SyntheticStringToken` is a token whose value is independent of it's type. | 1906 * A token whose value is independent of it's type. |
| 1927 */ | 1907 */ |
| 1928 class SyntheticStringToken extends StringToken { | 1908 class SyntheticStringToken extends StringToken { |
| 1929 /** | 1909 /** |
| 1930 * Initialize a newly created token to represent a token of the given [type] | 1910 * Initialize a newly created token to represent a token of the given [type] |
| 1931 * with the given [value] at the given [offset]. | 1911 * with the given [value] at the given [offset]. |
| 1932 */ | 1912 */ |
| 1933 SyntheticStringToken(TokenType type, String value, int offset) | 1913 SyntheticStringToken(TokenType type, String value, int offset) |
| 1934 : super(type, value, offset); | 1914 : super(type, value, offset); |
| 1935 | 1915 |
| 1936 @override | 1916 @override |
| 1937 bool get isSynthetic => true; | 1917 bool get isSynthetic => true; |
| 1938 } | 1918 } |
| 1939 | 1919 |
| 1940 /** | 1920 /** |
| 1941 * Instances of the class `Token` represent a token that was scanned from the | 1921 * A token that was scanned from the input. Each token knows which tokens |
| 1942 * input. Each token knows which tokens preceed and follow it, acting as a link | 1922 * precede and follow it, acting as a link in a doubly linked list of tokens. |
| 1943 * in a doubly linked list of tokens. | |
| 1944 */ | 1923 */ |
| 1945 class Token { | 1924 class Token { |
| 1946 /** | 1925 /** |
| 1947 * The type of the token. | 1926 * The type of the token. |
| 1948 */ | 1927 */ |
| 1949 final TokenType type; | 1928 final TokenType type; |
| 1950 | 1929 |
| 1951 /** | 1930 /** |
| 1952 * The offset from the beginning of the file to the first character in the | 1931 * The offset from the beginning of the file to the first character in the |
| 1953 * token. | 1932 * token. |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2120 if (token != null && (offset < 0 || token.offset < offset)) { | 2099 if (token != null && (offset < 0 || token.offset < offset)) { |
| 2121 first = token; | 2100 first = token; |
| 2122 offset = token.offset; | 2101 offset = token.offset; |
| 2123 } | 2102 } |
| 2124 } | 2103 } |
| 2125 return first; | 2104 return first; |
| 2126 } | 2105 } |
| 2127 } | 2106 } |
| 2128 | 2107 |
| 2129 /** | 2108 /** |
| 2130 * The enumeration `TokenClass` represents classes (or groups) of tokens with a | 2109 * The classes (or groups) of tokens with a similar use. |
| 2131 * similar use. | |
| 2132 */ | 2110 */ |
| 2133 class TokenClass { | 2111 class TokenClass { |
| 2134 /** | 2112 /** |
| 2135 * A value used to indicate that the token type is not part of any specific | 2113 * A value used to indicate that the token type is not part of any specific |
| 2136 * class of token. | 2114 * class of token. |
| 2137 */ | 2115 */ |
| 2138 static const TokenClass NO_CLASS = const TokenClass('NO_CLASS'); | 2116 static const TokenClass NO_CLASS = const TokenClass('NO_CLASS'); |
| 2139 | 2117 |
| 2140 /** | 2118 /** |
| 2141 * A value used to indicate that the token type is an additive operator. | 2119 * A value used to indicate that the token type is an additive operator. |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2238 */ | 2216 */ |
| 2239 final int precedence; | 2217 final int precedence; |
| 2240 | 2218 |
| 2241 const TokenClass(this.name, [this.precedence = 0]); | 2219 const TokenClass(this.name, [this.precedence = 0]); |
| 2242 | 2220 |
| 2243 @override | 2221 @override |
| 2244 String toString() => name; | 2222 String toString() => name; |
| 2245 } | 2223 } |
| 2246 | 2224 |
| 2247 /** | 2225 /** |
| 2248 * The enumeration `TokenType` defines the types of tokens that can be returned | 2226 * The types of tokens that can be returned by the scanner. |
| 2249 * by the scanner. | |
| 2250 */ | 2227 */ |
| 2251 class TokenType { | 2228 class TokenType { |
| 2252 /** | 2229 /** |
| 2253 * The type of the token that marks the end of the input. | 2230 * The type of the token that marks the end of the input. |
| 2254 */ | 2231 */ |
| 2255 static const TokenType EOF = const TokenType_EOF('EOF'); | 2232 static const TokenType EOF = const TokenType_EOF('EOF'); |
| 2256 | 2233 |
| 2257 static const TokenType DOUBLE = const TokenType('DOUBLE'); | 2234 static const TokenType DOUBLE = const TokenType('DOUBLE'); |
| 2258 | 2235 |
| 2259 static const TokenType HEXADECIMAL = const TokenType('HEXADECIMAL'); | 2236 static const TokenType HEXADECIMAL = const TokenType('HEXADECIMAL'); |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2580 } | 2557 } |
| 2581 | 2558 |
| 2582 class TokenType_EOF extends TokenType { | 2559 class TokenType_EOF extends TokenType { |
| 2583 const TokenType_EOF(String name) : super(name, TokenClass.NO_CLASS, ""); | 2560 const TokenType_EOF(String name) : super(name, TokenClass.NO_CLASS, ""); |
| 2584 | 2561 |
| 2585 @override | 2562 @override |
| 2586 String toString() => "-eof-"; | 2563 String toString() => "-eof-"; |
| 2587 } | 2564 } |
| 2588 | 2565 |
| 2589 /** | 2566 /** |
| 2590 * A `TokenWithComment` is a normal token that is preceded by comments. | 2567 * A normal token that is preceded by comments. |
| 2591 */ | 2568 */ |
| 2592 class TokenWithComment extends Token { | 2569 class TokenWithComment extends Token { |
| 2593 /** | 2570 /** |
| 2594 * The first comment in the list of comments that precede this token. | 2571 * The first comment in the list of comments that precede this token. |
| 2595 */ | 2572 */ |
| 2596 CommentToken _precedingComment; | 2573 CommentToken _precedingComment; |
| 2597 | 2574 |
| 2598 /** | 2575 /** |
| 2599 * Initialize a newly created token to have the given [type] at the given | 2576 * Initialize a newly created token to have the given [type] at the given |
| 2600 * [offset] and to be preceded by the comments reachable from the given | 2577 * [offset] and to be preceded by the comments reachable from the given |
| 2601 * [comment]. | 2578 * [comment]. |
| 2602 */ | 2579 */ |
| 2603 TokenWithComment(TokenType type, int offset, this._precedingComment) | 2580 TokenWithComment(TokenType type, int offset, this._precedingComment) |
| 2604 : super(type, offset) { | 2581 : super(type, offset) { |
| 2605 _setCommentParent(_precedingComment); | 2582 _setCommentParent(_precedingComment); |
| 2606 } | 2583 } |
| 2607 | 2584 |
| 2608 CommentToken get precedingComments => _precedingComment; | 2585 CommentToken get precedingComments => _precedingComment; |
| 2609 | 2586 |
| 2610 void set precedingComments(CommentToken comment) { | 2587 void set precedingComments(CommentToken comment) { |
| 2611 _precedingComment = comment; | 2588 _precedingComment = comment; |
| 2612 _setCommentParent(_precedingComment); | 2589 _setCommentParent(_precedingComment); |
| 2613 } | 2590 } |
| 2614 | 2591 |
| 2615 @override | 2592 @override |
| 2616 Token copy() => new TokenWithComment(type, offset, precedingComments); | 2593 Token copy() => new TokenWithComment(type, offset, precedingComments); |
| 2617 } | 2594 } |
| OLD | NEW |