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 /// A pair of tokens marking the beginning and the end of a span. Use for error | |
173 /// reporting. | |
174 class TokenPair implements Spannable { | |
175 final Token begin; | |
176 final Token end; | |
177 | |
178 TokenPair(this.begin, this.end); | |
179 } | |
180 | |
181 /** | |
182 * A [SymbolToken] represents the symbol in its precendence info. | |
183 * Also used for end of file with EOF_INFO. | |
184 */ | |
185 class SymbolToken extends Token { | |
186 | |
187 final PrecedenceInfo info; | |
188 | |
189 SymbolToken(this.info, int charOffset) : super(charOffset); | |
190 | |
191 String get value => info.value; | |
192 | |
193 String get stringValue => info.value; | |
194 | |
195 bool isIdentifier() => false; | |
196 | |
197 String toString() => "SymbolToken($value)"; | |
198 } | |
199 | |
200 /** | |
201 * A [BeginGroupToken] represents a symbol that may be the beginning of | |
202 * a pair of brackets, i.e., ( { [ < or ${ | |
203 * The [endGroup] token points to the matching closing bracked in case | |
204 * it can be identified during scanning. | |
205 */ | |
206 class BeginGroupToken extends SymbolToken { | |
207 Token endGroup; | |
208 | |
209 BeginGroupToken(PrecedenceInfo info, int charOffset) | |
210 : super(info, charOffset); | |
211 } | |
212 | |
213 /** | |
214 * A keyword token. | |
215 */ | |
216 class KeywordToken extends Token { | |
217 final Keyword keyword; | |
218 | |
219 KeywordToken(this.keyword, int charOffset) : super(charOffset); | |
220 | |
221 PrecedenceInfo get info => keyword.info; | |
222 | |
223 String get value => keyword.syntax; | |
224 | |
225 String get stringValue => keyword.syntax; | |
226 | |
227 bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn; | |
228 | |
229 String toString() => "KeywordToken($value)"; | |
230 } | |
231 | |
232 abstract class ErrorToken extends Token { | |
233 ErrorToken(int charOffset) | |
234 : super(charOffset); | |
235 | |
236 PrecedenceInfo get info => BAD_INPUT_INFO; | |
237 | |
238 String get value { | |
239 throw new SpannableAssertionFailure(this, assertionMessage); | |
240 } | |
241 | |
242 String get stringValue => null; | |
243 | |
244 bool isIdentifier() => false; | |
245 | |
246 String get assertionMessage; | |
247 } | |
248 | |
249 class BadInputToken extends ErrorToken { | |
250 final int character; | |
251 | |
252 BadInputToken(this.character, int charOffset) | |
253 : super(charOffset); | |
254 | |
255 String toString() => "BadInputToken($character)"; | |
256 | |
257 String get assertionMessage { | |
258 return 'Character U+${character.toRadixString(16)} not allowed here.'; | |
259 } | |
260 } | |
261 | |
262 class UnterminatedToken extends ErrorToken { | |
263 final String start; | |
264 final int endOffset; | |
265 | |
266 UnterminatedToken(this.start, int charOffset, this.endOffset) | |
267 : super(charOffset); | |
268 | |
269 String toString() => "UnterminatedToken($start)"; | |
270 | |
271 String get assertionMessage => "'$start' isn't terminated."; | |
272 | |
273 int get charCount => endOffset - charOffset; | |
274 } | |
275 | |
276 class UnmatchedToken extends ErrorToken { | |
277 final BeginGroupToken begin; | |
278 | |
279 UnmatchedToken(BeginGroupToken begin) | |
280 : this.begin = begin, | |
281 super(begin.charOffset); | |
282 | |
283 String toString() => "UnmatchedToken(${begin.value})"; | |
284 | |
285 String get assertionMessage => "'$begin' isn't closed."; | |
286 } | |
287 | |
288 /** | |
289 * A String-valued token. Represents identifiers, string literals, | |
290 * number literals, comments, and error tokens, using the corresponding | |
291 * precedence info. | |
292 */ | |
293 class StringToken extends Token { | |
294 /** | |
295 * The length threshold above which substring tokens are computed lazily. | |
296 * | |
297 * For string tokens that are substrings of the program source, the actual | |
298 * substring extraction is performed lazily. This is beneficial because | |
299 * not all scanned code is actually used. For unused parts, the substrings | |
300 * are never computed and allocated. | |
301 */ | |
302 static const int LAZY_THRESHOLD = 4; | |
303 | |
304 var /* String | LazySubtring */ valueOrLazySubstring; | |
305 | |
306 final PrecedenceInfo info; | |
307 | |
308 /** | |
309 * Creates a non-lazy string token. If [canonicalize] is true, the string | |
310 * is canonicalized before the token is created. | |
311 */ | |
312 StringToken.fromString(this.info, String value, int charOffset, | |
313 {bool canonicalize : false}) | |
314 : valueOrLazySubstring = canonicalizedString(value, canonicalize), | |
315 super(charOffset); | |
316 | |
317 /** | |
318 * Creates a lazy string token. If [canonicalize] is true, the string | |
319 * is canonicalized before the token is created. | |
320 */ | |
321 StringToken.fromSubstring(this.info, String data, int start, int end, | |
322 int charOffset, {bool canonicalize : false}) | |
323 : super(charOffset) { | |
324 int length = end - start; | |
325 if (length <= LAZY_THRESHOLD) { | |
326 valueOrLazySubstring = canonicalizedString(data.substring(start, end), | |
327 canonicalize); | |
328 } else { | |
329 valueOrLazySubstring = | |
330 new LazySubstring(data, start, length, canonicalize); | |
331 } | |
332 } | |
333 | |
334 /** | |
335 * Creates a lazy string token. If [asciiOnly] is false, the byte array | |
336 * is passed through a UTF-8 decoder. | |
337 */ | |
338 StringToken.fromUtf8Bytes(this.info, List<int> data, int start, int end, | |
339 bool asciiOnly, int charOffset) | |
340 : super(charOffset) { | |
341 int length = end - start; | |
342 if (length <= LAZY_THRESHOLD) { | |
343 valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly); | |
344 } else { | |
345 valueOrLazySubstring = new LazySubstring(data, start, length, asciiOnly); | |
346 } | |
347 } | |
348 | |
349 String get value { | |
350 if (valueOrLazySubstring is String) { | |
351 return valueOrLazySubstring; | |
352 } else { | |
353 assert(valueOrLazySubstring is LazySubstring); | |
354 var data = valueOrLazySubstring.data; | |
355 int start = valueOrLazySubstring.start; | |
356 int end = start + valueOrLazySubstring.length; | |
357 if (data is String) { | |
358 valueOrLazySubstring = canonicalizedString( | |
359 data.substring(start, end), valueOrLazySubstring.boolValue); | |
360 } else { | |
361 valueOrLazySubstring = decodeUtf8( | |
362 data, start, end, valueOrLazySubstring.boolValue); | |
363 } | |
364 return valueOrLazySubstring; | |
365 } | |
366 } | |
367 | |
368 String get stringValue => null; | |
369 | |
370 bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN); | |
371 | |
372 String toString() => "StringToken($value)"; | |
373 | |
374 static final HashSet<String> canonicalizedSubstrings = | |
375 new HashSet<String>(); | |
376 | |
377 static String canonicalizedString(String s, bool canonicalize) { | |
378 if (!canonicalize) return s; | |
379 var result = canonicalizedSubstrings.lookup(s); | |
380 if (result != null) return result; | |
381 canonicalizedSubstrings.add(s); | |
382 return s; | |
383 } | |
384 | |
385 static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) { | |
386 var s; | |
387 if (asciiOnly) { | |
388 // getRange returns an iterator, it does not copy the data. | |
389 s = new String.fromCharCodes(data.getRange(start, end)); | |
390 } else { | |
391 // TODO(lry): this is measurably slow. Also sublist is copied eagerly. | |
392 var bytes = data.sublist(start, end); | |
393 s = UTF8.decode(bytes); | |
394 } | |
395 return canonicalizedString(s, true); | |
396 } | |
397 } | |
398 | |
399 /** | |
400 * This class represents the necessary information to compute a substring | |
401 * lazily. The substring can either originate from a string or from | |
402 * a [:List<int>:] of UTF-8 bytes. | |
403 */ | |
404 abstract class LazySubstring { | |
405 /** The original data, either a string or a List<int> */ | |
406 get data; | |
407 | |
408 int get start; | |
409 int get length; | |
410 | |
411 /** | |
412 * If this substring is based on a String, the [boolValue] indicates wheter | |
413 * the resulting substring should be canonicalized. | |
414 * | |
415 * For substrings based on a byte array, the [boolValue] is true if the | |
416 * array only holds ASCII characters. The resulting substring will be | |
417 * canonicalized after decoding. | |
418 */ | |
419 bool get boolValue; | |
420 | |
421 LazySubstring.internal(); | |
422 | |
423 factory LazySubstring(data, int start, int length, bool b) { | |
424 // See comment on [CompactLazySubstring]. | |
425 if (start < 0x100000 && length < 0x200) { | |
426 int fields = (start << 9); | |
427 fields = fields | length; | |
428 fields = fields << 1; | |
429 if (b) fields |= 1; | |
430 return new CompactLazySubstring(data, fields); | |
431 } else { | |
432 return new FullLazySubstring(data, start, length, b); | |
433 } | |
434 } | |
435 } | |
436 | |
437 /** | |
438 * This class encodes [start], [length] and [boolValue] in a single | |
439 * 30 bit integer. It uses 20 bits for [start], which covers source files | |
440 * of 1MB. [length] has 9 bits, which covers 512 characters. | |
441 * | |
442 * The file html_dart2js.dart is currently around 1MB. | |
443 */ | |
444 class CompactLazySubstring extends LazySubstring { | |
445 final data; | |
446 final int fields; | |
447 | |
448 CompactLazySubstring(this.data, this.fields) : super.internal(); | |
449 | |
450 int get start => fields >> 10; | |
451 int get length => (fields >> 1) & 0x1ff; | |
452 bool get boolValue => (fields & 1) == 1; | |
453 } | |
454 | |
455 class FullLazySubstring extends LazySubstring { | |
456 final data; | |
457 final int start; | |
458 final int length; | |
459 final bool boolValue; | |
460 FullLazySubstring(this.data, this.start, this.length, this.boolValue) | |
461 : super.internal(); | |
462 } | |
463 | |
464 bool isUserDefinableOperator(String value) { | |
465 return | |
466 isBinaryOperator(value) || | |
467 isMinusOperator(value) || | |
468 isTernaryOperator(value) || | |
469 isUnaryOperator(value); | |
470 } | |
471 | |
472 bool isUnaryOperator(String value) => identical(value, '~'); | |
473 | |
474 bool isBinaryOperator(String value) { | |
475 return | |
476 (identical(value, '==')) || | |
477 (identical(value, '[]')) || | |
478 (identical(value, '*')) || | |
479 (identical(value, '/')) || | |
480 (identical(value, '%')) || | |
481 (identical(value, '~/')) || | |
482 (identical(value, '+')) || | |
483 (identical(value, '<<')) || | |
484 (identical(value, '>>')) || | |
485 (identical(value, '>=')) || | |
486 (identical(value, '>')) || | |
487 (identical(value, '<=')) || | |
488 (identical(value, '<')) || | |
489 (identical(value, '&')) || | |
490 (identical(value, '^')) || | |
491 (identical(value, '|')); | |
492 } | |
493 | |
494 bool isTernaryOperator(String value) => identical(value, '[]='); | |
495 | |
496 bool isMinusOperator(String value) => identical(value, '-'); | |
497 | |
498 class PrecedenceInfo { | |
499 final String value; | |
500 final int precedence; | |
501 final int kind; | |
502 | |
503 const PrecedenceInfo(this.value, this.precedence, this.kind); | |
504 | |
505 toString() => 'PrecedenceInfo($value, $precedence, $kind)'; | |
506 | |
507 int get hashCode => computeHashCode(value, precedence, kind); | |
508 } | |
509 | |
510 // TODO(ahe): The following are not tokens in Dart. | |
511 const PrecedenceInfo BACKPING_INFO = | |
512 const PrecedenceInfo('`', 0, BACKPING_TOKEN); | |
513 const PrecedenceInfo BACKSLASH_INFO = | |
514 const PrecedenceInfo('\\', 0, BACKSLASH_TOKEN); | |
515 const PrecedenceInfo PERIOD_PERIOD_PERIOD_INFO = | |
516 const PrecedenceInfo('...', 0, | |
517 PERIOD_PERIOD_PERIOD_TOKEN); | |
518 | |
519 /** | |
520 * The cascade operator has the lowest precedence of any operator | |
521 * except assignment. | |
522 */ | |
523 const int CASCADE_PRECEDENCE = 2; | |
524 const PrecedenceInfo PERIOD_PERIOD_INFO = | |
525 const PrecedenceInfo('..', CASCADE_PRECEDENCE, | |
526 PERIOD_PERIOD_TOKEN); | |
527 | |
528 const PrecedenceInfo BANG_INFO = | |
529 const PrecedenceInfo('!', 0, BANG_TOKEN); | |
530 const PrecedenceInfo COLON_INFO = | |
531 const PrecedenceInfo(':', 0, COLON_TOKEN); | |
532 const PrecedenceInfo INDEX_INFO = | |
533 const PrecedenceInfo('[]', 0, INDEX_TOKEN); | |
534 const PrecedenceInfo MINUS_MINUS_INFO = | |
535 const PrecedenceInfo('--', POSTFIX_PRECEDENCE, | |
536 MINUS_MINUS_TOKEN); | |
537 const PrecedenceInfo PLUS_PLUS_INFO = | |
538 const PrecedenceInfo('++', POSTFIX_PRECEDENCE, | |
539 PLUS_PLUS_TOKEN); | |
540 const PrecedenceInfo TILDE_INFO = | |
541 const PrecedenceInfo('~', 0, TILDE_TOKEN); | |
542 | |
543 const PrecedenceInfo FUNCTION_INFO = | |
544 const PrecedenceInfo('=>', 0, FUNCTION_TOKEN); | |
545 const PrecedenceInfo HASH_INFO = | |
546 const PrecedenceInfo('#', 0, HASH_TOKEN); | |
547 const PrecedenceInfo INDEX_EQ_INFO = | |
548 const PrecedenceInfo('[]=', 0, INDEX_EQ_TOKEN); | |
549 const PrecedenceInfo SEMICOLON_INFO = | |
550 const PrecedenceInfo(';', 0, SEMICOLON_TOKEN); | |
551 const PrecedenceInfo COMMA_INFO = | |
552 const PrecedenceInfo(',', 0, COMMA_TOKEN); | |
553 | |
554 const PrecedenceInfo AT_INFO = | |
555 const PrecedenceInfo('@', 0, AT_TOKEN); | |
556 | |
557 // Assignment operators. | |
558 const int ASSIGNMENT_PRECEDENCE = 1; | |
559 const PrecedenceInfo AMPERSAND_EQ_INFO = | |
560 const PrecedenceInfo('&=', | |
561 ASSIGNMENT_PRECEDENCE, AMPERSAND_EQ_TOKEN); | |
562 const PrecedenceInfo BAR_EQ_INFO = | |
563 const PrecedenceInfo('|=', | |
564 ASSIGNMENT_PRECEDENCE, BAR_EQ_TOKEN); | |
565 const PrecedenceInfo CARET_EQ_INFO = | |
566 const PrecedenceInfo('^=', | |
567 ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN); | |
568 const PrecedenceInfo EQ_INFO = | |
569 const PrecedenceInfo('=', | |
570 ASSIGNMENT_PRECEDENCE, EQ_TOKEN); | |
571 const PrecedenceInfo GT_GT_EQ_INFO = | |
572 const PrecedenceInfo('>>=', | |
573 ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN); | |
574 const PrecedenceInfo LT_LT_EQ_INFO = | |
575 const PrecedenceInfo('<<=', | |
576 ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN); | |
577 const PrecedenceInfo MINUS_EQ_INFO = | |
578 const PrecedenceInfo('-=', | |
579 ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN); | |
580 const PrecedenceInfo PERCENT_EQ_INFO = | |
581 const PrecedenceInfo('%=', | |
582 ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN); | |
583 const PrecedenceInfo PLUS_EQ_INFO = | |
584 const PrecedenceInfo('+=', | |
585 ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN); | |
586 const PrecedenceInfo SLASH_EQ_INFO = | |
587 const PrecedenceInfo('/=', | |
588 ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN); | |
589 const PrecedenceInfo STAR_EQ_INFO = | |
590 const PrecedenceInfo('*=', | |
591 ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN); | |
592 const PrecedenceInfo TILDE_SLASH_EQ_INFO = | |
593 const PrecedenceInfo('~/=', | |
594 ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN); | |
595 | |
596 const PrecedenceInfo QUESTION_INFO = | |
597 const PrecedenceInfo('?', 3, QUESTION_TOKEN); | |
598 | |
599 const PrecedenceInfo BAR_BAR_INFO = | |
600 const PrecedenceInfo('||', 4, BAR_BAR_TOKEN); | |
601 | |
602 const PrecedenceInfo AMPERSAND_AMPERSAND_INFO = | |
603 const PrecedenceInfo('&&', 5, AMPERSAND_AMPERSAND_TOKEN); | |
604 | |
605 const PrecedenceInfo BAR_INFO = | |
606 const PrecedenceInfo('|', 8, BAR_TOKEN); | |
607 | |
608 const PrecedenceInfo CARET_INFO = | |
609 const PrecedenceInfo('^', 9, CARET_TOKEN); | |
610 | |
611 const PrecedenceInfo AMPERSAND_INFO = | |
612 const PrecedenceInfo('&', 10, AMPERSAND_TOKEN); | |
613 | |
614 // Equality operators. | |
615 const int EQUALITY_PRECEDENCE = 6; | |
616 const PrecedenceInfo BANG_EQ_EQ_INFO = | |
617 const PrecedenceInfo('!==', | |
618 EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN); | |
619 const PrecedenceInfo BANG_EQ_INFO = | |
620 const PrecedenceInfo('!=', | |
621 EQUALITY_PRECEDENCE, BANG_EQ_TOKEN); | |
622 const PrecedenceInfo EQ_EQ_EQ_INFO = | |
623 const PrecedenceInfo('===', | |
624 EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN); | |
625 const PrecedenceInfo EQ_EQ_INFO = | |
626 const PrecedenceInfo('==', | |
627 EQUALITY_PRECEDENCE, EQ_EQ_TOKEN); | |
628 | |
629 // Relational operators. | |
630 const int RELATIONAL_PRECEDENCE = 7; | |
631 const PrecedenceInfo GT_EQ_INFO = | |
632 const PrecedenceInfo('>=', | |
633 RELATIONAL_PRECEDENCE, GT_EQ_TOKEN); | |
634 const PrecedenceInfo GT_INFO = | |
635 const PrecedenceInfo('>', | |
636 RELATIONAL_PRECEDENCE, GT_TOKEN); | |
637 const PrecedenceInfo IS_INFO = | |
638 const PrecedenceInfo('is', | |
639 RELATIONAL_PRECEDENCE, KEYWORD_TOKEN); | |
640 const PrecedenceInfo AS_INFO = | |
641 const PrecedenceInfo('as', | |
642 RELATIONAL_PRECEDENCE, KEYWORD_TOKEN); | |
643 const PrecedenceInfo LT_EQ_INFO = | |
644 const PrecedenceInfo('<=', | |
645 RELATIONAL_PRECEDENCE, LT_EQ_TOKEN); | |
646 const PrecedenceInfo LT_INFO = | |
647 const PrecedenceInfo('<', | |
648 RELATIONAL_PRECEDENCE, LT_TOKEN); | |
649 | |
650 // Shift operators. | |
651 const PrecedenceInfo GT_GT_INFO = | |
652 const PrecedenceInfo('>>', 11, GT_GT_TOKEN); | |
653 const PrecedenceInfo LT_LT_INFO = | |
654 const PrecedenceInfo('<<', 11, LT_LT_TOKEN); | |
655 | |
656 // Additive operators. | |
657 const PrecedenceInfo MINUS_INFO = | |
658 const PrecedenceInfo('-', 12, MINUS_TOKEN); | |
659 const PrecedenceInfo PLUS_INFO = | |
660 const PrecedenceInfo('+', 12, PLUS_TOKEN); | |
661 | |
662 // Multiplicative operators. | |
663 const PrecedenceInfo PERCENT_INFO = | |
664 const PrecedenceInfo('%', 13, PERCENT_TOKEN); | |
665 const PrecedenceInfo SLASH_INFO = | |
666 const PrecedenceInfo('/', 13, SLASH_TOKEN); | |
667 const PrecedenceInfo STAR_INFO = | |
668 const PrecedenceInfo('*', 13, STAR_TOKEN); | |
669 const PrecedenceInfo TILDE_SLASH_INFO = | |
670 const PrecedenceInfo('~/', 13, TILDE_SLASH_TOKEN); | |
671 | |
672 const int POSTFIX_PRECEDENCE = 14; | |
673 const PrecedenceInfo PERIOD_INFO = | |
674 const PrecedenceInfo('.', POSTFIX_PRECEDENCE, | |
675 PERIOD_TOKEN); | |
676 | |
677 const PrecedenceInfo KEYWORD_INFO = | |
678 const PrecedenceInfo('keyword', 0, KEYWORD_TOKEN); | |
679 | |
680 const PrecedenceInfo EOF_INFO = | |
681 const PrecedenceInfo('EOF', 0, EOF_TOKEN); | |
682 | |
683 const PrecedenceInfo IDENTIFIER_INFO = | |
684 const PrecedenceInfo('identifier', 0, IDENTIFIER_TOKEN); | |
685 | |
686 const PrecedenceInfo BAD_INPUT_INFO = | |
687 const PrecedenceInfo('malformed input', 0, | |
688 BAD_INPUT_TOKEN); | |
689 | |
690 const PrecedenceInfo OPEN_PAREN_INFO = | |
691 const PrecedenceInfo('(', POSTFIX_PRECEDENCE, | |
692 OPEN_PAREN_TOKEN); | |
693 | |
694 const PrecedenceInfo CLOSE_PAREN_INFO = | |
695 const PrecedenceInfo(')', 0, CLOSE_PAREN_TOKEN); | |
696 | |
697 const PrecedenceInfo OPEN_CURLY_BRACKET_INFO = | |
698 const PrecedenceInfo('{', 0, OPEN_CURLY_BRACKET_TOKEN); | |
699 | |
700 const PrecedenceInfo CLOSE_CURLY_BRACKET_INFO = | |
701 const PrecedenceInfo('}', 0, CLOSE_CURLY_BRACKET_TOKEN); | |
702 | |
703 const PrecedenceInfo INT_INFO = | |
704 const PrecedenceInfo('int', 0, INT_TOKEN); | |
705 | |
706 const PrecedenceInfo STRING_INFO = | |
707 const PrecedenceInfo('string', 0, STRING_TOKEN); | |
708 | |
709 const PrecedenceInfo OPEN_SQUARE_BRACKET_INFO = | |
710 const PrecedenceInfo('[', POSTFIX_PRECEDENCE, | |
711 OPEN_SQUARE_BRACKET_TOKEN); | |
712 | |
713 const PrecedenceInfo CLOSE_SQUARE_BRACKET_INFO = | |
714 const PrecedenceInfo(']', 0, CLOSE_SQUARE_BRACKET_TOKEN); | |
715 | |
716 const PrecedenceInfo DOUBLE_INFO = | |
717 const PrecedenceInfo('double', 0, DOUBLE_TOKEN); | |
718 | |
719 const PrecedenceInfo STRING_INTERPOLATION_INFO = | |
720 const PrecedenceInfo('\${', 0, | |
721 STRING_INTERPOLATION_TOKEN); | |
722 | |
723 const PrecedenceInfo STRING_INTERPOLATION_IDENTIFIER_INFO = | |
724 const PrecedenceInfo('\$', 0, | |
725 STRING_INTERPOLATION_IDENTIFIER_TOKEN); | |
726 | |
727 const PrecedenceInfo HEXADECIMAL_INFO = | |
728 const PrecedenceInfo('hexadecimal', 0, HEXADECIMAL_TOKEN); | |
729 | |
730 const PrecedenceInfo COMMENT_INFO = | |
731 const PrecedenceInfo('comment', 0, COMMENT_TOKEN); | |
OLD | NEW |