| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 fasta.scanner.token; | 5 library fasta.scanner.token; |
| 6 | 6 |
| 7 import 'keyword.dart' show Keyword; | 7 import 'keyword.dart' show Keyword; |
| 8 | 8 |
| 9 import 'precedence.dart' show BAD_INPUT_INFO, EOF_INFO, PrecedenceInfo; | 9 import 'precedence.dart' show BAD_INPUT_INFO, EOF_INFO, PrecedenceInfo; |
| 10 | 10 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 * The precedence info for this token. [info] determines the kind and the | 49 * The precedence info for this token. [info] determines the kind and the |
| 50 * precedence level of this token. | 50 * precedence level of this token. |
| 51 * | 51 * |
| 52 * Defined as getter to save a field in the [KeywordToken] subclass. | 52 * Defined as getter to save a field in the [KeywordToken] subclass. |
| 53 */ | 53 */ |
| 54 PrecedenceInfo get info; | 54 PrecedenceInfo get info; |
| 55 | 55 |
| 56 /** | 56 /** |
| 57 * The string represented by this token, a substring of the source code. | 57 * The string represented by this token, a substring of the source code. |
| 58 * | 58 * |
| 59 * For [StringToken]s the [value] includes the quotes, explicit escapes, etc. | 59 * For [StringToken]s the [lexeme] includes the quotes, explicit escapes, etc. |
| 60 */ | 60 */ |
| 61 String get value; | 61 String get lexeme; |
| 62 | 62 |
| 63 /** | 63 /** |
| 64 * For symbol and keyword tokens, returns the string value represented by this | 64 * For symbol and keyword tokens, returns the string value represented by this |
| 65 * token. For [StringToken]s this method returns [:null:]. | 65 * token. For [StringToken]s this method returns [:null:]. |
| 66 * | 66 * |
| 67 * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time | 67 * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time |
| 68 * constant originating in the [PrecedenceInfo] or in the [Keyword] instance. | 68 * constant originating in the [PrecedenceInfo] or in the [Keyword] instance. |
| 69 * This allows testing for keywords and symbols using [:identical:], e.g., | 69 * This allows testing for keywords and symbols using [:identical:], e.g., |
| 70 * [:identical('class', token.value):]. | 70 * [:identical('class', token.value):]. |
| 71 * | 71 * |
| 72 * Note that returning [:null:] for string tokens is important to identify | 72 * Note that returning [:null:] for string tokens is important to identify |
| 73 * symbols and keywords, we cannot use [value] instead. The string literal | 73 * symbols and keywords, we cannot use [lexeme] instead. The string literal |
| 74 * "$a($b" | 74 * "$a($b" |
| 75 * produces ..., SymbolToken($), StringToken(a), StringToken((), ... | 75 * produces ..., SymbolToken($), StringToken(a), StringToken((), ... |
| 76 * | 76 * |
| 77 * After parsing the identifier 'a', the parser tests for a function | 77 * After parsing the identifier 'a', the parser tests for a function |
| 78 * declaration using [:identical(next.stringValue, '('):], which (rightfully) | 78 * declaration using [:identical(next.stringValue, '('):], which (rightfully) |
| 79 * returns false because stringValue returns [:null:]. | 79 * returns false because stringValue returns [:null:]. |
| 80 */ | 80 */ |
| 81 String get stringValue; | 81 String get stringValue; |
| 82 | 82 |
| 83 /** | 83 /** |
| (...skipping 11 matching lines...) Expand all Loading... |
| 95 * see implementation in [KeywordToken]. | 95 * see implementation in [KeywordToken]. |
| 96 */ | 96 */ |
| 97 bool isIdentifier(); | 97 bool isIdentifier(); |
| 98 | 98 |
| 99 /** | 99 /** |
| 100 * Returns a textual representation of this token to be used for debugging | 100 * Returns a textual representation of this token to be used for debugging |
| 101 * purposes. The resulting string might contain information about the | 101 * purposes. The resulting string might contain information about the |
| 102 * structure of the token, for example 'StringToken(foo)' for the identifier | 102 * structure of the token, for example 'StringToken(foo)' for the identifier |
| 103 * token 'foo'. | 103 * token 'foo'. |
| 104 * | 104 * |
| 105 * Use [value] for the text actually parsed by the token. | 105 * Use [lexeme] for the text actually parsed by the token. |
| 106 */ | 106 */ |
| 107 String toString(); | 107 String toString(); |
| 108 | 108 |
| 109 /** | 109 /** |
| 110 * The number of characters parsed by this token. | 110 * The number of characters parsed by this token. |
| 111 */ | 111 */ |
| 112 int get charCount { | 112 int get charCount { |
| 113 if (info == BAD_INPUT_INFO) { | 113 if (info == BAD_INPUT_INFO) { |
| 114 // This is a token that wraps around an error message. Return 1 | 114 // This is a token that wraps around an error message. Return 1 |
| 115 // instead of the size of the length of the error message. | 115 // instead of the size of the length of the error message. |
| 116 return 1; | 116 return 1; |
| 117 } else { | 117 } else { |
| 118 return value.length; | 118 return lexeme.length; |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 | 121 |
| 122 /// The character offset of the end of this token within the source text. | 122 /// The character offset of the end of this token within the source text. |
| 123 int get charEnd => charOffset + charCount; | 123 int get charEnd => charOffset + charCount; |
| 124 | 124 |
| 125 bool get isEof => false; | 125 bool get isEof => false; |
| 126 } | 126 } |
| 127 | 127 |
| 128 /** | 128 /** |
| 129 * A [SymbolToken] represents the symbol in its precedence info. | 129 * A [SymbolToken] represents the symbol in its precedence info. |
| 130 * Also used for end of file with EOF_INFO. | 130 * Also used for end of file with EOF_INFO. |
| 131 */ | 131 */ |
| 132 class SymbolToken extends Token { | 132 class SymbolToken extends Token { |
| 133 final PrecedenceInfo info; | 133 final PrecedenceInfo info; |
| 134 | 134 |
| 135 SymbolToken(this.info, int charOffset) : super(charOffset); | 135 SymbolToken(this.info, int charOffset) : super(charOffset); |
| 136 | 136 |
| 137 String get value => info.value; | 137 String get lexeme => info.value; |
| 138 | 138 |
| 139 String get stringValue => info.value; | 139 String get stringValue => info.value; |
| 140 | 140 |
| 141 bool isIdentifier() => false; | 141 bool isIdentifier() => false; |
| 142 | 142 |
| 143 String toString() => "SymbolToken($value)"; | 143 String toString() => "SymbolToken($lexeme)"; |
| 144 | 144 |
| 145 bool get isEof => info == EOF_INFO; | 145 bool get isEof => info == EOF_INFO; |
| 146 } | 146 } |
| 147 | 147 |
| 148 /** | 148 /** |
| 149 * A [BeginGroupToken] represents a symbol that may be the beginning of | 149 * A [BeginGroupToken] represents a symbol that may be the beginning of |
| 150 * a pair of brackets, i.e., ( { [ < or ${ | 150 * a pair of brackets, i.e., ( { [ < or ${ |
| 151 * The [endGroup] token points to the matching closing bracked in case | 151 * The [endGroup] token points to the matching closing bracked in case |
| 152 * it can be identified during scanning. | 152 * it can be identified during scanning. |
| 153 */ | 153 */ |
| 154 class BeginGroupToken extends SymbolToken { | 154 class BeginGroupToken extends SymbolToken { |
| 155 Token endGroup; | 155 Token endGroup; |
| 156 | 156 |
| 157 BeginGroupToken(PrecedenceInfo info, int charOffset) | 157 BeginGroupToken(PrecedenceInfo info, int charOffset) |
| 158 : super(info, charOffset); | 158 : super(info, charOffset); |
| 159 } | 159 } |
| 160 | 160 |
| 161 /** | 161 /** |
| 162 * A keyword token. | 162 * A keyword token. |
| 163 */ | 163 */ |
| 164 class KeywordToken extends Token { | 164 class KeywordToken extends Token { |
| 165 final Keyword keyword; | 165 final Keyword keyword; |
| 166 | 166 |
| 167 KeywordToken(this.keyword, int charOffset) : super(charOffset); | 167 KeywordToken(this.keyword, int charOffset) : super(charOffset); |
| 168 | 168 |
| 169 PrecedenceInfo get info => keyword.info; | 169 PrecedenceInfo get info => keyword.info; |
| 170 | 170 |
| 171 String get value => keyword.syntax; | 171 String get lexeme => keyword.syntax; |
| 172 | 172 |
| 173 String get stringValue => keyword.syntax; | 173 String get stringValue => keyword.syntax; |
| 174 | 174 |
| 175 bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn; | 175 bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn; |
| 176 | 176 |
| 177 String toString() => "KeywordToken($value)"; | 177 String toString() => "KeywordToken($lexeme)"; |
| 178 } | 178 } |
| 179 | 179 |
| 180 /** | 180 /** |
| 181 * A String-valued token. Represents identifiers, string literals, | 181 * A String-valued token. Represents identifiers, string literals, |
| 182 * number literals, comments, and error tokens, using the corresponding | 182 * number literals, comments, and error tokens, using the corresponding |
| 183 * precedence info. | 183 * precedence info. |
| 184 */ | 184 */ |
| 185 class StringToken extends Token { | 185 class StringToken extends Token { |
| 186 /** | 186 /** |
| 187 * The length threshold above which substring tokens are computed lazily. | 187 * The length threshold above which substring tokens are computed lazily. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 bool asciiOnly, int charOffset) | 233 bool asciiOnly, int charOffset) |
| 234 : super(charOffset) { | 234 : super(charOffset) { |
| 235 int length = end - start; | 235 int length = end - start; |
| 236 if (length <= LAZY_THRESHOLD) { | 236 if (length <= LAZY_THRESHOLD) { |
| 237 valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly); | 237 valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly); |
| 238 } else { | 238 } else { |
| 239 valueOrLazySubstring = new LazySubstring(data, start, length, asciiOnly); | 239 valueOrLazySubstring = new LazySubstring(data, start, length, asciiOnly); |
| 240 } | 240 } |
| 241 } | 241 } |
| 242 | 242 |
| 243 String get value { | 243 String get lexeme { |
| 244 if (valueOrLazySubstring is String) { | 244 if (valueOrLazySubstring is String) { |
| 245 return valueOrLazySubstring; | 245 return valueOrLazySubstring; |
| 246 } else { | 246 } else { |
| 247 assert(valueOrLazySubstring is LazySubstring); | 247 assert(valueOrLazySubstring is LazySubstring); |
| 248 var data = valueOrLazySubstring.data; | 248 var data = valueOrLazySubstring.data; |
| 249 int start = valueOrLazySubstring.start; | 249 int start = valueOrLazySubstring.start; |
| 250 int end = start + valueOrLazySubstring.length; | 250 int end = start + valueOrLazySubstring.length; |
| 251 if (data is String) { | 251 if (data is String) { |
| 252 valueOrLazySubstring = canonicalizedString( | 252 valueOrLazySubstring = canonicalizedString( |
| 253 data, start, end, valueOrLazySubstring.boolValue); | 253 data, start, end, valueOrLazySubstring.boolValue); |
| 254 } else { | 254 } else { |
| 255 valueOrLazySubstring = | 255 valueOrLazySubstring = |
| 256 decodeUtf8(data, start, end, valueOrLazySubstring.boolValue); | 256 decodeUtf8(data, start, end, valueOrLazySubstring.boolValue); |
| 257 } | 257 } |
| 258 return valueOrLazySubstring; | 258 return valueOrLazySubstring; |
| 259 } | 259 } |
| 260 } | 260 } |
| 261 | 261 |
| 262 /// See [Token.stringValue] for an explanation. | 262 /// See [Token.stringValue] for an explanation. |
| 263 String get stringValue => null; | 263 String get stringValue => null; |
| 264 | 264 |
| 265 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN); | 265 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN); |
| 266 | 266 |
| 267 String toString() => "StringToken($value)"; | 267 String toString() => "StringToken($lexeme)"; |
| 268 | 268 |
| 269 static final StringCanonicalizer canonicalizer = new StringCanonicalizer(); | 269 static final StringCanonicalizer canonicalizer = new StringCanonicalizer(); |
| 270 | 270 |
| 271 static String canonicalizedString( | 271 static String canonicalizedString( |
| 272 String s, int start, int end, bool canonicalize) { | 272 String s, int start, int end, bool canonicalize) { |
| 273 if (!canonicalize) return s; | 273 if (!canonicalize) return s; |
| 274 return canonicalizer.canonicalize(s, start, end, false); | 274 return canonicalizer.canonicalize(s, start, end, false); |
| 275 } | 275 } |
| 276 | 276 |
| 277 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) { | 277 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 identical(value, "<=") || | 368 identical(value, "<=") || |
| 369 identical(value, "<") || | 369 identical(value, "<") || |
| 370 identical(value, "&") || | 370 identical(value, "&") || |
| 371 identical(value, "^") || | 371 identical(value, "^") || |
| 372 identical(value, "|"); | 372 identical(value, "|"); |
| 373 } | 373 } |
| 374 | 374 |
| 375 bool isTernaryOperator(String value) => identical(value, "[]="); | 375 bool isTernaryOperator(String value) => identical(value, "[]="); |
| 376 | 376 |
| 377 bool isMinusOperator(String value) => identical(value, "-"); | 377 bool isMinusOperator(String value) => identical(value, "-"); |
| OLD | NEW |