| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of scanner; | |
| 6 | |
| 7 const int EOF_TOKEN = 0; | |
| 8 | |
| 9 const int KEYWORD_TOKEN = $k; | |
| 10 const int IDENTIFIER_TOKEN = $a; | |
| 11 const int BAD_INPUT_TOKEN = $X; | |
| 12 const int DOUBLE_TOKEN = $d; | |
| 13 const int INT_TOKEN = $i; | |
| 14 const int HEXADECIMAL_TOKEN = $x; | |
| 15 const int STRING_TOKEN = $SQ; | |
| 16 | |
| 17 const int AMPERSAND_TOKEN = $AMPERSAND; | |
| 18 const int BACKPING_TOKEN = $BACKPING; | |
| 19 const int BACKSLASH_TOKEN = $BACKSLASH; | |
| 20 const int BANG_TOKEN = $BANG; | |
| 21 const int BAR_TOKEN = $BAR; | |
| 22 const int COLON_TOKEN = $COLON; | |
| 23 const int COMMA_TOKEN = $COMMA; | |
| 24 const int EQ_TOKEN = $EQ; | |
| 25 const int GT_TOKEN = $GT; | |
| 26 const int HASH_TOKEN = $HASH; | |
| 27 const int OPEN_CURLY_BRACKET_TOKEN = $OPEN_CURLY_BRACKET; | |
| 28 const int OPEN_SQUARE_BRACKET_TOKEN = $OPEN_SQUARE_BRACKET; | |
| 29 const int OPEN_PAREN_TOKEN = $OPEN_PAREN; | |
| 30 const int LT_TOKEN = $LT; | |
| 31 const int MINUS_TOKEN = $MINUS; | |
| 32 const int PERIOD_TOKEN = $PERIOD; | |
| 33 const int PLUS_TOKEN = $PLUS; | |
| 34 const int QUESTION_TOKEN = $QUESTION; | |
| 35 const int AT_TOKEN = $AT; | |
| 36 const int CLOSE_CURLY_BRACKET_TOKEN = $CLOSE_CURLY_BRACKET; | |
| 37 const int CLOSE_SQUARE_BRACKET_TOKEN = $CLOSE_SQUARE_BRACKET; | |
| 38 const int CLOSE_PAREN_TOKEN = $CLOSE_PAREN; | |
| 39 const int SEMICOLON_TOKEN = $SEMICOLON; | |
| 40 const int SLASH_TOKEN = $SLASH; | |
| 41 const int TILDE_TOKEN = $TILDE; | |
| 42 const int STAR_TOKEN = $STAR; | |
| 43 const int PERCENT_TOKEN = $PERCENT; | |
| 44 const int CARET_TOKEN = $CARET; | |
| 45 | |
| 46 const int STRING_INTERPOLATION_TOKEN = 128; | |
| 47 const int LT_EQ_TOKEN = STRING_INTERPOLATION_TOKEN + 1; | |
| 48 const int FUNCTION_TOKEN = LT_EQ_TOKEN + 1; | |
| 49 const int SLASH_EQ_TOKEN = FUNCTION_TOKEN + 1; | |
| 50 const int PERIOD_PERIOD_PERIOD_TOKEN = SLASH_EQ_TOKEN + 1; | |
| 51 const int PERIOD_PERIOD_TOKEN = PERIOD_PERIOD_PERIOD_TOKEN + 1; | |
| 52 const int EQ_EQ_EQ_TOKEN = PERIOD_PERIOD_TOKEN + 1; | |
| 53 const int EQ_EQ_TOKEN = EQ_EQ_EQ_TOKEN + 1; | |
| 54 const int LT_LT_EQ_TOKEN = EQ_EQ_TOKEN + 1; | |
| 55 const int LT_LT_TOKEN = LT_LT_EQ_TOKEN + 1; | |
| 56 const int GT_EQ_TOKEN = LT_LT_TOKEN + 1; | |
| 57 const int GT_GT_EQ_TOKEN = GT_EQ_TOKEN + 1; | |
| 58 const int INDEX_EQ_TOKEN = GT_GT_EQ_TOKEN + 1; | |
| 59 const int INDEX_TOKEN = INDEX_EQ_TOKEN + 1; | |
| 60 const int BANG_EQ_EQ_TOKEN = INDEX_TOKEN + 1; | |
| 61 const int BANG_EQ_TOKEN = BANG_EQ_EQ_TOKEN + 1; | |
| 62 const int AMPERSAND_AMPERSAND_TOKEN = BANG_EQ_TOKEN + 1; | |
| 63 const int AMPERSAND_EQ_TOKEN = AMPERSAND_AMPERSAND_TOKEN + 1; | |
| 64 const int BAR_BAR_TOKEN = AMPERSAND_EQ_TOKEN + 1; | |
| 65 const int BAR_EQ_TOKEN = BAR_BAR_TOKEN + 1; | |
| 66 const int STAR_EQ_TOKEN = BAR_EQ_TOKEN + 1; | |
| 67 const int PLUS_PLUS_TOKEN = STAR_EQ_TOKEN + 1; | |
| 68 const int PLUS_EQ_TOKEN = PLUS_PLUS_TOKEN + 1; | |
| 69 const int MINUS_MINUS_TOKEN = PLUS_EQ_TOKEN + 1; | |
| 70 const int MINUS_EQ_TOKEN = MINUS_MINUS_TOKEN + 1; | |
| 71 const int TILDE_SLASH_EQ_TOKEN = MINUS_EQ_TOKEN + 1; | |
| 72 const int TILDE_SLASH_TOKEN = TILDE_SLASH_EQ_TOKEN + 1; | |
| 73 const int PERCENT_EQ_TOKEN = TILDE_SLASH_TOKEN + 1; | |
| 74 const int GT_GT_TOKEN = PERCENT_EQ_TOKEN + 1; | |
| 75 const int CARET_EQ_TOKEN = GT_GT_TOKEN + 1; | |
| 76 const int COMMENT_TOKEN = CARET_EQ_TOKEN + 1; | |
| 77 const int STRING_INTERPOLATION_IDENTIFIER_TOKEN = COMMENT_TOKEN + 1; | |
| 78 | |
| 79 /** | |
| 80 * A token that doubles as a linked list. | |
| 81 */ | |
| 82 abstract class Token implements Spannable { | |
| 83 /** | |
| 84 * The character offset of the start of this token within the source text. | |
| 85 */ | |
| 86 final int charOffset; | |
| 87 | |
| 88 Token(this.charOffset); | |
| 89 | |
| 90 /** | |
| 91 * The next token in the token stream. | |
| 92 */ | |
| 93 Token next; | |
| 94 | |
| 95 /** | |
| 96 * The precedence info for this token. [info] determines the kind and the | |
| 97 * precedence level of this token. | |
| 98 * | |
| 99 * Defined as getter to save a field in the [KeywordToken] subclass. | |
| 100 */ | |
| 101 PrecedenceInfo get info; | |
| 102 | |
| 103 /** | |
| 104 * The string represented by this token, a substring of the source code. | |
| 105 * | |
| 106 * For [StringToken]s the [value] includes the quotes, explicit escapes, etc. | |
| 107 */ | |
| 108 String get value; | |
| 109 | |
| 110 /** | |
| 111 * For symbol and keyword tokens, returns the string value represented by this | |
| 112 * token. For [StringToken]s this method returns [:null:]. | |
| 113 * | |
| 114 * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time | |
| 115 * constant originating in the [PrecedenceInfo] or in the [Keyword] instance. | |
| 116 * This allows testing for keywords and symbols using [:identical:], e.g., | |
| 117 * [:identical('class', token.value):]. | |
| 118 * | |
| 119 * Note that returning [:null:] for string tokens is important to identify | |
| 120 * symbols and keywords, we cannot use [value] instead. The string literal | |
| 121 * "$a($b" | |
| 122 * produces ..., SymbolToken($), StringToken(a), StringToken((), ... | |
| 123 * | |
| 124 * After parsing the identifier 'a', the parser tests for a function | |
| 125 * declaration using [:identical(next.stringValue, '('):], which (rihgtfully) | |
| 126 * returns false because stringValue returns [:null:]. | |
| 127 */ | |
| 128 String get stringValue; | |
| 129 | |
| 130 /** | |
| 131 * The kind enum of this token as determined by its [info]. | |
| 132 */ | |
| 133 int get kind => info.kind; | |
| 134 | |
| 135 /** | |
| 136 * The precedence level for this token. | |
| 137 */ | |
| 138 int get precedence => info.precedence; | |
| 139 | |
| 140 /** | |
| 141 * True if this token is an identifier. Some keywords allowed as identifiers, | |
| 142 * see implementation in [KeywordToken]. | |
| 143 */ | |
| 144 bool isIdentifier(); | |
| 145 | |
| 146 /** | |
| 147 * Returns a textual representation of this token to be used for debugging | |
| 148 * purposes. The resulting string might contain information about the | |
| 149 * structure of the token, for example 'StringToken(foo)' for the identifier | |
| 150 * token 'foo'. | |
| 151 * | |
| 152 * Use [value] for the text actually parsed by the token. | |
| 153 */ | |
| 154 String toString(); | |
| 155 | |
| 156 /** | |
| 157 * The number of characters parsed by this token. | |
| 158 */ | |
| 159 int get charCount { | |
| 160 if (info == BAD_INPUT_INFO) { | |
| 161 // This is a token that wraps around an error message. Return 1 | |
| 162 // instead of the size of the length of the error message. | |
| 163 return 1; | |
| 164 } else { | |
| 165 return value.length; | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 int get hashCode => computeHashCode(charOffset, info, value); | |
| 170 } | |
| 171 | |
| 172 /** | |
| 173 * A [SymbolToken] represents the symbol in its precendence info. | |
| 174 * Also used for end of file with EOF_INFO. | |
| 175 */ | |
| 176 class SymbolToken extends Token { | |
| 177 | |
| 178 final PrecedenceInfo info; | |
| 179 | |
| 180 SymbolToken(this.info, int charOffset) : super(charOffset); | |
| 181 | |
| 182 String get value => info.value; | |
| 183 | |
| 184 String get stringValue => info.value; | |
| 185 | |
| 186 bool isIdentifier() => false; | |
| 187 | |
| 188 String toString() => "SymbolToken($value)"; | |
| 189 } | |
| 190 | |
| 191 /** | |
| 192 * A [BeginGroupToken] represents a symbol that may be the beginning of | |
| 193 * a pair of brackets, i.e., ( { [ < or ${ | |
| 194 * The [endGroup] token points to the matching closing bracked in case | |
| 195 * it can be identified during scanning. | |
| 196 */ | |
| 197 class BeginGroupToken extends SymbolToken { | |
| 198 Token endGroup; | |
| 199 | |
| 200 BeginGroupToken(PrecedenceInfo info, int charOffset) | |
| 201 : super(info, charOffset); | |
| 202 } | |
| 203 | |
| 204 /** | |
| 205 * A keyword token. | |
| 206 */ | |
| 207 class KeywordToken extends Token { | |
| 208 final Keyword keyword; | |
| 209 | |
| 210 KeywordToken(this.keyword, int charOffset) : super(charOffset); | |
| 211 | |
| 212 PrecedenceInfo get info => keyword.info; | |
| 213 | |
| 214 String get value => keyword.syntax; | |
| 215 | |
| 216 String get stringValue => keyword.syntax; | |
| 217 | |
| 218 bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn; | |
| 219 | |
| 220 String toString() => "KeywordToken($value)"; | |
| 221 } | |
| 222 | |
| 223 abstract class ErrorToken extends Token { | |
| 224 ErrorToken(int charOffset) | |
| 225 : super(charOffset); | |
| 226 | |
| 227 PrecedenceInfo get info => BAD_INPUT_INFO; | |
| 228 | |
| 229 String get value { | |
| 230 throw new SpannableAssertionFailure(this, assertionMessage); | |
| 231 } | |
| 232 | |
| 233 String get stringValue => null; | |
| 234 | |
| 235 bool isIdentifier() => false; | |
| 236 | |
| 237 String get assertionMessage; | |
| 238 } | |
| 239 | |
| 240 class BadInputToken extends ErrorToken { | |
| 241 final int character; | |
| 242 | |
| 243 BadInputToken(this.character, int charOffset) | |
| 244 : super(charOffset); | |
| 245 | |
| 246 String toString() => "BadInputToken($character)"; | |
| 247 | |
| 248 String get assertionMessage { | |
| 249 return 'Character U+${character.toRadixString(16)} not allowed here.'; | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 class UnterminatedToken extends ErrorToken { | |
| 254 final String start; | |
| 255 final int endOffset; | |
| 256 | |
| 257 UnterminatedToken(this.start, int charOffset, this.endOffset) | |
| 258 : super(charOffset); | |
| 259 | |
| 260 String toString() => "UnterminatedToken($start)"; | |
| 261 | |
| 262 String get assertionMessage => "'$start' isn't terminated."; | |
| 263 | |
| 264 int get charCount => endOffset - charOffset; | |
| 265 } | |
| 266 | |
| 267 class UnmatchedToken extends ErrorToken { | |
| 268 final BeginGroupToken begin; | |
| 269 | |
| 270 UnmatchedToken(BeginGroupToken begin) | |
| 271 : this.begin = begin, | |
| 272 super(begin.charOffset); | |
| 273 | |
| 274 String toString() => "UnmatchedToken(${begin.value})"; | |
| 275 | |
| 276 String get assertionMessage => "'$begin' isn't closed."; | |
| 277 } | |
| 278 | |
| 279 /** | |
| 280 * A String-valued token. Represents identifiers, string literals, | |
| 281 * number literals, comments, and error tokens, using the corresponding | |
| 282 * precedence info. | |
| 283 */ | |
| 284 class StringToken extends Token { | |
| 285 /** | |
| 286 * The length threshold above which substring tokens are computed lazily. | |
| 287 * | |
| 288 * For string tokens that are substrings of the program source, the actual | |
| 289 * substring extraction is performed lazily. This is beneficial because | |
| 290 * not all scanned code is actually used. For unused parts, the substrings | |
| 291 * are never computed and allocated. | |
| 292 */ | |
| 293 static const int LAZY_THRESHOLD = 4; | |
| 294 | |
| 295 var /* String | LazySubtring */ valueOrLazySubstring; | |
| 296 | |
| 297 final PrecedenceInfo info; | |
| 298 | |
| 299 /** | |
| 300 * Creates a non-lazy string token. If [canonicalize] is true, the string | |
| 301 * is canonicalized before the token is created. | |
| 302 */ | |
| 303 StringToken.fromString(this.info, String value, int charOffset, | |
| 304 {bool canonicalize : false}) | |
| 305 : valueOrLazySubstring = canonicalizedString(value, canonicalize), | |
| 306 super(charOffset); | |
| 307 | |
| 308 /** | |
| 309 * Creates a lazy string token. If [canonicalize] is true, the string | |
| 310 * is canonicalized before the token is created. | |
| 311 */ | |
| 312 StringToken.fromSubstring(this.info, String data, int start, int end, | |
| 313 int charOffset, {bool canonicalize : false}) | |
| 314 : super(charOffset) { | |
| 315 int length = end - start; | |
| 316 if (length <= LAZY_THRESHOLD) { | |
| 317 valueOrLazySubstring = canonicalizedString(data.substring(start, end), | |
| 318 canonicalize); | |
| 319 } else { | |
| 320 valueOrLazySubstring = | |
| 321 new LazySubstring(data, start, length, canonicalize); | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 /** | |
| 326 * Creates a lazy string token. If [asciiOnly] is false, the byte array | |
| 327 * is passed through a UTF-8 decoder. | |
| 328 */ | |
| 329 StringToken.fromUtf8Bytes(this.info, List<int> data, int start, int end, | |
| 330 bool asciiOnly, int charOffset) | |
| 331 : super(charOffset) { | |
| 332 int length = end - start; | |
| 333 if (length <= LAZY_THRESHOLD) { | |
| 334 valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly); | |
| 335 } else { | |
| 336 valueOrLazySubstring = new LazySubstring(data, start, length, asciiOnly); | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 String get value { | |
| 341 if (valueOrLazySubstring is String) { | |
| 342 return valueOrLazySubstring; | |
| 343 } else { | |
| 344 assert(valueOrLazySubstring is LazySubstring); | |
| 345 var data = valueOrLazySubstring.data; | |
| 346 int start = valueOrLazySubstring.start; | |
| 347 int end = start + valueOrLazySubstring.length; | |
| 348 if (data is String) { | |
| 349 valueOrLazySubstring = canonicalizedString( | |
| 350 data.substring(start, end), valueOrLazySubstring.boolValue); | |
| 351 } else { | |
| 352 valueOrLazySubstring = decodeUtf8( | |
| 353 data, start, end, valueOrLazySubstring.boolValue); | |
| 354 } | |
| 355 return valueOrLazySubstring; | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 String get stringValue => null; | |
| 360 | |
| 361 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN); | |
| 362 | |
| 363 String toString() => "StringToken($value)"; | |
| 364 | |
| 365 static final HashSet<String> canonicalizedSubstrings = | |
| 366 new HashSet<String>(); | |
| 367 | |
| 368 static String canonicalizedString(String s, bool canonicalize) { | |
| 369 if (!canonicalize) return s; | |
| 370 var result = canonicalizedSubstrings.lookup(s); | |
| 371 if (result != null) return result; | |
| 372 canonicalizedSubstrings.add(s); | |
| 373 return s; | |
| 374 } | |
| 375 | |
| 376 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) { | |
| 377 var s; | |
| 378 if (asciiOnly) { | |
| 379 // getRange returns an iterator, it does not copy the data. | |
| 380 s = new String.fromCharCodes(data.getRange(start, end)); | |
| 381 } else { | |
| 382 // TODO(lry): this is measurably slow. Also sublist is copied eagerly. | |
| 383 var bytes = data.sublist(start, end); | |
| 384 s = UTF8.decode(bytes); | |
| 385 } | |
| 386 return canonicalizedString(s, true); | |
| 387 } | |
| 388 } | |
| 389 | |
| 390 /** | |
| 391 * This class represents the necessary information to compute a substring | |
| 392 * lazily. The substring can either originate from a string or from | |
| 393 * a [:List<int>:] of UTF-8 bytes. | |
| 394 */ | |
| 395 abstract class LazySubstring { | |
| 396 /** The original data, either a string or a List<int> */ | |
| 397 get data; | |
| 398 | |
| 399 int get start; | |
| 400 int get length; | |
| 401 | |
| 402 /** | |
| 403 * If this substring is based on a String, the [boolValue] indicates wheter | |
| 404 * the resulting substring should be canonicalized. | |
| 405 * | |
| 406 * For substrings based on a byte array, the [boolValue] is true if the | |
| 407 * array only holds ASCII characters. The resulting substring will be | |
| 408 * canonicalized after decoding. | |
| 409 */ | |
| 410 bool get boolValue; | |
| 411 | |
| 412 LazySubstring.internal(); | |
| 413 | |
| 414 factory LazySubstring(data, int start, int length, bool b) { | |
| 415 // See comment on [CompactLazySubstring]. | |
| 416 if (start < 0x100000 && length < 0x200) { | |
| 417 int fields = (start << 9); | |
| 418 fields = fields | length; | |
| 419 fields = fields << 1; | |
| 420 if (b) fields |= 1; | |
| 421 return new CompactLazySubstring(data, fields); | |
| 422 } else { | |
| 423 return new FullLazySubstring(data, start, length, b); | |
| 424 } | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 /** | |
| 429 * This class encodes [start], [length] and [boolValue] in a single | |
| 430 * 30 bit integer. It uses 20 bits for [start], which covers source files | |
| 431 * of 1MB. [length] has 9 bits, which covers 512 characters. | |
| 432 * | |
| 433 * The file html_dart2js.dart is currently around 1MB. | |
| 434 */ | |
| 435 class CompactLazySubstring extends LazySubstring { | |
| 436 final data; | |
| 437 final int fields; | |
| 438 | |
| 439 CompactLazySubstring(this.data, this.fields) : super.internal(); | |
| 440 | |
| 441 int get start => fields >> 10; | |
| 442 int get length => (fields >> 1) & 0x1ff; | |
| 443 bool get boolValue => (fields & 1) == 1; | |
| 444 } | |
| 445 | |
| 446 class FullLazySubstring extends LazySubstring { | |
| 447 final data; | |
| 448 final int start; | |
| 449 final int length; | |
| 450 final bool boolValue; | |
| 451 FullLazySubstring(this.data, this.start, this.length, this.boolValue) | |
| 452 : super.internal(); | |
| 453 } | |
| 454 | |
| 455 bool isUserDefinableOperator(String value) { | |
| 456 return | |
| 457 isBinaryOperator(value) || | |
| 458 isMinusOperator(value) || | |
| 459 isTernaryOperator(value) || | |
| 460 isUnaryOperator(value); | |
| 461 } | |
| 462 | |
| 463 bool isUnaryOperator(String value) => identical(value, '~'); | |
| 464 | |
| 465 bool isBinaryOperator(String value) { | |
| 466 return | |
| 467 (identical(value, '==')) || | |
| 468 (identical(value, '[]')) || | |
| 469 (identical(value, '*')) || | |
| 470 (identical(value, '/')) || | |
| 471 (identical(value, '%')) || | |
| 472 (identical(value, '~/')) || | |
| 473 (identical(value, '+')) || | |
| 474 (identical(value, '<<')) || | |
| 475 (identical(value, '>>')) || | |
| 476 (identical(value, '>=')) || | |
| 477 (identical(value, '>')) || | |
| 478 (identical(value, '<=')) || | |
| 479 (identical(value, '<')) || | |
| 480 (identical(value, '&')) || | |
| 481 (identical(value, '^')) || | |
| 482 (identical(value, '|')); | |
| 483 } | |
| 484 | |
| 485 bool isTernaryOperator(String value) => identical(value, '[]='); | |
| 486 | |
| 487 bool isMinusOperator(String value) => identical(value, '-'); | |
| 488 | |
| 489 class PrecedenceInfo { | |
| 490 final String value; | |
| 491 final int precedence; | |
| 492 final int kind; | |
| 493 | |
| 494 const PrecedenceInfo(this.value, this.precedence, this.kind); | |
| 495 | |
| 496 toString() => 'PrecedenceInfo($value, $precedence, $kind)'; | |
| 497 | |
| 498 int get hashCode => computeHashCode(value, precedence, kind); | |
| 499 } | |
| 500 | |
| 501 // TODO(ahe): The following are not tokens in Dart. | |
| 502 const PrecedenceInfo BACKPING_INFO = | |
| 503 const PrecedenceInfo('`', 0, BACKPING_TOKEN); | |
| 504 const PrecedenceInfo BACKSLASH_INFO = | |
| 505 const PrecedenceInfo('\\', 0, BACKSLASH_TOKEN); | |
| 506 const PrecedenceInfo PERIOD_PERIOD_PERIOD_INFO = | |
| 507 const PrecedenceInfo('...', 0, | |
| 508 PERIOD_PERIOD_PERIOD_TOKEN); | |
| 509 | |
| 510 /** | |
| 511 * The cascade operator has the lowest precedence of any operator | |
| 512 * except assignment. | |
| 513 */ | |
| 514 const int CASCADE_PRECEDENCE = 2; | |
| 515 const PrecedenceInfo PERIOD_PERIOD_INFO = | |
| 516 const PrecedenceInfo('..', CASCADE_PRECEDENCE, | |
| 517 PERIOD_PERIOD_TOKEN); | |
| 518 | |
| 519 const PrecedenceInfo BANG_INFO = | |
| 520 const PrecedenceInfo('!', 0, BANG_TOKEN); | |
| 521 const PrecedenceInfo COLON_INFO = | |
| 522 const PrecedenceInfo(':', 0, COLON_TOKEN); | |
| 523 const PrecedenceInfo INDEX_INFO = | |
| 524 const PrecedenceInfo('[]', 0, INDEX_TOKEN); | |
| 525 const PrecedenceInfo MINUS_MINUS_INFO = | |
| 526 const PrecedenceInfo('--', POSTFIX_PRECEDENCE, | |
| 527 MINUS_MINUS_TOKEN); | |
| 528 const PrecedenceInfo PLUS_PLUS_INFO = | |
| 529 const PrecedenceInfo('++', POSTFIX_PRECEDENCE, | |
| 530 PLUS_PLUS_TOKEN); | |
| 531 const PrecedenceInfo TILDE_INFO = | |
| 532 const PrecedenceInfo('~', 0, TILDE_TOKEN); | |
| 533 | |
| 534 const PrecedenceInfo FUNCTION_INFO = | |
| 535 const PrecedenceInfo('=>', 0, FUNCTION_TOKEN); | |
| 536 const PrecedenceInfo HASH_INFO = | |
| 537 const PrecedenceInfo('#', 0, HASH_TOKEN); | |
| 538 const PrecedenceInfo INDEX_EQ_INFO = | |
| 539 const PrecedenceInfo('[]=', 0, INDEX_EQ_TOKEN); | |
| 540 const PrecedenceInfo SEMICOLON_INFO = | |
| 541 const PrecedenceInfo(';', 0, SEMICOLON_TOKEN); | |
| 542 const PrecedenceInfo COMMA_INFO = | |
| 543 const PrecedenceInfo(',', 0, COMMA_TOKEN); | |
| 544 | |
| 545 const PrecedenceInfo AT_INFO = | |
| 546 const PrecedenceInfo('@', 0, AT_TOKEN); | |
| 547 | |
| 548 // Assignment operators. | |
| 549 const int ASSIGNMENT_PRECEDENCE = 1; | |
| 550 const PrecedenceInfo AMPERSAND_EQ_INFO = | |
| 551 const PrecedenceInfo('&=', | |
| 552 ASSIGNMENT_PRECEDENCE, AMPERSAND_EQ_TOKEN); | |
| 553 const PrecedenceInfo BAR_EQ_INFO = | |
| 554 const PrecedenceInfo('|=', | |
| 555 ASSIGNMENT_PRECEDENCE, BAR_EQ_TOKEN); | |
| 556 const PrecedenceInfo CARET_EQ_INFO = | |
| 557 const PrecedenceInfo('^=', | |
| 558 ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN); | |
| 559 const PrecedenceInfo EQ_INFO = | |
| 560 const PrecedenceInfo('=', | |
| 561 ASSIGNMENT_PRECEDENCE, EQ_TOKEN); | |
| 562 const PrecedenceInfo GT_GT_EQ_INFO = | |
| 563 const PrecedenceInfo('>>=', | |
| 564 ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN); | |
| 565 const PrecedenceInfo LT_LT_EQ_INFO = | |
| 566 const PrecedenceInfo('<<=', | |
| 567 ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN); | |
| 568 const PrecedenceInfo MINUS_EQ_INFO = | |
| 569 const PrecedenceInfo('-=', | |
| 570 ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN); | |
| 571 const PrecedenceInfo PERCENT_EQ_INFO = | |
| 572 const PrecedenceInfo('%=', | |
| 573 ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN); | |
| 574 const PrecedenceInfo PLUS_EQ_INFO = | |
| 575 const PrecedenceInfo('+=', | |
| 576 ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN); | |
| 577 const PrecedenceInfo SLASH_EQ_INFO = | |
| 578 const PrecedenceInfo('/=', | |
| 579 ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN); | |
| 580 const PrecedenceInfo STAR_EQ_INFO = | |
| 581 const PrecedenceInfo('*=', | |
| 582 ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN); | |
| 583 const PrecedenceInfo TILDE_SLASH_EQ_INFO = | |
| 584 const PrecedenceInfo('~/=', | |
| 585 ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN); | |
| 586 | |
| 587 const PrecedenceInfo QUESTION_INFO = | |
| 588 const PrecedenceInfo('?', 3, QUESTION_TOKEN); | |
| 589 | |
| 590 const PrecedenceInfo BAR_BAR_INFO = | |
| 591 const PrecedenceInfo('||', 4, BAR_BAR_TOKEN); | |
| 592 | |
| 593 const PrecedenceInfo AMPERSAND_AMPERSAND_INFO = | |
| 594 const PrecedenceInfo('&&', 5, AMPERSAND_AMPERSAND_TOKEN); | |
| 595 | |
| 596 const PrecedenceInfo BAR_INFO = | |
| 597 const PrecedenceInfo('|', 8, BAR_TOKEN); | |
| 598 | |
| 599 const PrecedenceInfo CARET_INFO = | |
| 600 const PrecedenceInfo('^', 9, CARET_TOKEN); | |
| 601 | |
| 602 const PrecedenceInfo AMPERSAND_INFO = | |
| 603 const PrecedenceInfo('&', 10, AMPERSAND_TOKEN); | |
| 604 | |
| 605 // Equality operators. | |
| 606 const int EQUALITY_PRECEDENCE = 6; | |
| 607 const PrecedenceInfo BANG_EQ_EQ_INFO = | |
| 608 const PrecedenceInfo('!==', | |
| 609 EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN); | |
| 610 const PrecedenceInfo BANG_EQ_INFO = | |
| 611 const PrecedenceInfo('!=', | |
| 612 EQUALITY_PRECEDENCE, BANG_EQ_TOKEN); | |
| 613 const PrecedenceInfo EQ_EQ_EQ_INFO = | |
| 614 const PrecedenceInfo('===', | |
| 615 EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN); | |
| 616 const PrecedenceInfo EQ_EQ_INFO = | |
| 617 const PrecedenceInfo('==', | |
| 618 EQUALITY_PRECEDENCE, EQ_EQ_TOKEN); | |
| 619 | |
| 620 // Relational operators. | |
| 621 const int RELATIONAL_PRECEDENCE = 7; | |
| 622 const PrecedenceInfo GT_EQ_INFO = | |
| 623 const PrecedenceInfo('>=', | |
| 624 RELATIONAL_PRECEDENCE, GT_EQ_TOKEN); | |
| 625 const PrecedenceInfo GT_INFO = | |
| 626 const PrecedenceInfo('>', | |
| 627 RELATIONAL_PRECEDENCE, GT_TOKEN); | |
| 628 const PrecedenceInfo IS_INFO = | |
| 629 const PrecedenceInfo('is', | |
| 630 RELATIONAL_PRECEDENCE, KEYWORD_TOKEN); | |
| 631 const PrecedenceInfo AS_INFO = | |
| 632 const PrecedenceInfo('as', | |
| 633 RELATIONAL_PRECEDENCE, KEYWORD_TOKEN); | |
| 634 const PrecedenceInfo LT_EQ_INFO = | |
| 635 const PrecedenceInfo('<=', | |
| 636 RELATIONAL_PRECEDENCE, LT_EQ_TOKEN); | |
| 637 const PrecedenceInfo LT_INFO = | |
| 638 const PrecedenceInfo('<', | |
| 639 RELATIONAL_PRECEDENCE, LT_TOKEN); | |
| 640 | |
| 641 // Shift operators. | |
| 642 const PrecedenceInfo GT_GT_INFO = | |
| 643 const PrecedenceInfo('>>', 11, GT_GT_TOKEN); | |
| 644 const PrecedenceInfo LT_LT_INFO = | |
| 645 const PrecedenceInfo('<<', 11, LT_LT_TOKEN); | |
| 646 | |
| 647 // Additive operators. | |
| 648 const PrecedenceInfo MINUS_INFO = | |
| 649 const PrecedenceInfo('-', 12, MINUS_TOKEN); | |
| 650 const PrecedenceInfo PLUS_INFO = | |
| 651 const PrecedenceInfo('+', 12, PLUS_TOKEN); | |
| 652 | |
| 653 // Multiplicative operators. | |
| 654 const PrecedenceInfo PERCENT_INFO = | |
| 655 const PrecedenceInfo('%', 13, PERCENT_TOKEN); | |
| 656 const PrecedenceInfo SLASH_INFO = | |
| 657 const PrecedenceInfo('/', 13, SLASH_TOKEN); | |
| 658 const PrecedenceInfo STAR_INFO = | |
| 659 const PrecedenceInfo('*', 13, STAR_TOKEN); | |
| 660 const PrecedenceInfo TILDE_SLASH_INFO = | |
| 661 const PrecedenceInfo('~/', 13, TILDE_SLASH_TOKEN); | |
| 662 | |
| 663 const int POSTFIX_PRECEDENCE = 14; | |
| 664 const PrecedenceInfo PERIOD_INFO = | |
| 665 const PrecedenceInfo('.', POSTFIX_PRECEDENCE, | |
| 666 PERIOD_TOKEN); | |
| 667 | |
| 668 const PrecedenceInfo KEYWORD_INFO = | |
| 669 const PrecedenceInfo('keyword', 0, KEYWORD_TOKEN); | |
| 670 | |
| 671 const PrecedenceInfo EOF_INFO = | |
| 672 const PrecedenceInfo('EOF', 0, EOF_TOKEN); | |
| 673 | |
| 674 const PrecedenceInfo IDENTIFIER_INFO = | |
| 675 const PrecedenceInfo('identifier', 0, IDENTIFIER_TOKEN); | |
| 676 | |
| 677 const PrecedenceInfo BAD_INPUT_INFO = | |
| 678 const PrecedenceInfo('malformed input', 0, | |
| 679 BAD_INPUT_TOKEN); | |
| 680 | |
| 681 const PrecedenceInfo OPEN_PAREN_INFO = | |
| 682 const PrecedenceInfo('(', POSTFIX_PRECEDENCE, | |
| 683 OPEN_PAREN_TOKEN); | |
| 684 | |
| 685 const PrecedenceInfo CLOSE_PAREN_INFO = | |
| 686 const PrecedenceInfo(')', 0, CLOSE_PAREN_TOKEN); | |
| 687 | |
| 688 const PrecedenceInfo OPEN_CURLY_BRACKET_INFO = | |
| 689 const PrecedenceInfo('{', 0, OPEN_CURLY_BRACKET_TOKEN); | |
| 690 | |
| 691 const PrecedenceInfo CLOSE_CURLY_BRACKET_INFO = | |
| 692 const PrecedenceInfo('}', 0, CLOSE_CURLY_BRACKET_TOKEN); | |
| 693 | |
| 694 const PrecedenceInfo INT_INFO = | |
| 695 const PrecedenceInfo('int', 0, INT_TOKEN); | |
| 696 | |
| 697 const PrecedenceInfo STRING_INFO = | |
| 698 const PrecedenceInfo('string', 0, STRING_TOKEN); | |
| 699 | |
| 700 const PrecedenceInfo OPEN_SQUARE_BRACKET_INFO = | |
| 701 const PrecedenceInfo('[', POSTFIX_PRECEDENCE, | |
| 702 OPEN_SQUARE_BRACKET_TOKEN); | |
| 703 | |
| 704 const PrecedenceInfo CLOSE_SQUARE_BRACKET_INFO = | |
| 705 const PrecedenceInfo(']', 0, CLOSE_SQUARE_BRACKET_TOKEN); | |
| 706 | |
| 707 const PrecedenceInfo DOUBLE_INFO = | |
| 708 const PrecedenceInfo('double', 0, DOUBLE_TOKEN); | |
| 709 | |
| 710 const PrecedenceInfo STRING_INTERPOLATION_INFO = | |
| 711 const PrecedenceInfo('\${', 0, | |
| 712 STRING_INTERPOLATION_TOKEN); | |
| 713 | |
| 714 const PrecedenceInfo STRING_INTERPOLATION_IDENTIFIER_INFO = | |
| 715 const PrecedenceInfo('\$', 0, | |
| 716 STRING_INTERPOLATION_IDENTIFIER_TOKEN); | |
| 717 | |
| 718 const PrecedenceInfo HEXADECIMAL_INFO = | |
| 719 const PrecedenceInfo('hexadecimal', 0, HEXADECIMAL_TOKEN); | |
| 720 | |
| 721 const PrecedenceInfo COMMENT_INFO = | |
| 722 const PrecedenceInfo('comment', 0, COMMENT_TOKEN); | |
| OLD | NEW |